diff --git a/CMakeLists.txt b/CMakeLists.txt index 38b98255a..a76f6cd17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(VERSION_REVISION "0") set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) -set(SDCARD_REVISION "0029") +set(SDCARD_REVISION "0034") set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION}) cmake_minimum_required(VERSION 2.8) diff --git a/CREDITS.txt b/CREDITS.txt index 4fcf98a29..95dc3e6a3 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -8,6 +8,7 @@ Romolo Manfredini (romoloman) Martin Hotař (mhotar) Maxim (Max) Paperno (mpaperno) Arne Schwabe (schwabe) +Daniel Gorbea (dgatf) [Translators] [fr] Sebastien Charpentier (LapinFou) @@ -31,6 +32,7 @@ Michael Byrne FlySky (monthly) JumperRC (monthly) RadioMaster (monthly) +HappyModel (monthly) Aloft Hobbies Jonathan Modellismo WsTech @@ -1761,3 +1763,182 @@ Paul Pearson Stuart Olson Pierre Connan Henk Eeltink +Robert Miller +George Walker +Александр Щитов +Heiko Polig +Gary Wild +Peter Sarcher +Steve Schoonover +Francisco Orcera Exposito +Alan Powell +Martin Eriksson +Wayne J Podaima +Tom Wilkinson +Fred Ceratt +Stefan Grunenberg +Aram Parsamyan +Wolfgang Rauser +John Wall +Martin Haggas +Denis Kelly +James Houck +Brian Stephanik +William McNeice +Sven De Boeck +SB Europe Ltd +Evening Shade Pottery +D van Oostveen +Michael Grosso +Carlos Marcal +d@taweb +Justin Digby +Hermann Vocat +Michael Francini +Michael Chambers +Harold H Youngren +Yann Orselli +Dieter Schaad +Ernst Camenzind +Ciobanu Rivelino Costel +David Jolly +Aram Parsamyan +Stewart Davies +Karsten Schwarz +Robert Mckay +Michael Oeschger +Randy Ling +Jonathan Wise +David Gardner +Christophe Judas +Lachlan Peters +Patrick C Kutschke +Thomas Halenbeck +Barry Wright +Nicolas Ducher +Giampiero Sintoni +Sidney B Harden +John Moody +Sylvain Cubizolles +Adam Kouse +FCG Kas +Dennis Marinus +James Donelson +Stefan Hassler +Reinhard Prix +Jeffrey Johnson +Michael Conway +Ryan Buffington +Thomas Horns +Michael Carnes +William Hallman +James Snodgrass +Michal Mesaros +James Lindner +Laurence Gerrard +Nico Wagner +Christoph Rössner +Ruben Flores +Jim Cukla +Lee Taylor +Stefan Kuster +Barry Wright +Steven Gilley +Lloyd Evans +Nolan O'Hearne +Jeffrey James N Buffie +James Houck +Andreas Arlt +William Walker +Salvador Munoz Vinas +Chris Geiger Photography +John F Smith +Robert Zecha +Fernando Martins +Martin Brungard +Paul Witko +Michael Campbell +Stuart Posnett +PK Doddema +Leonard MacKey +Andrew Peterson +Dominik Sedlacek +Ronald Hellstern +Vicente Suarez +Patrick Geerts +Rossi Giampaolo +Jose Luis Franco Torres +Bart Sillen +Antonio Moreno +Carolina Carcione +Lonnie Misner +John Eppling +Phillip Elliott +Robin Bayer +Jurij Peternel +George Aandahl +Guy Dangerfield +Thomas Limpert +Ismael G Zapater +Alan Hall +Bradley Goodwin +Paul Dittman +John Johnson +Liam Mahoney +Joseph Carr +Fiorenzo Agnelli +Brian Ramsey +Angelo Movio +Weldon Parks +Simon Brink +Weldon Parks +Ralf Herzenbruch +Ashley Pearce +SneakIT +Soaring Stuff +Jörg Lemnitz +Johann Gross +Mark Gibson +Rendall Assoc +Cozyn Holdings Pty Ltd +Tim Karsten +Nick Hesson +Laurent Lapassade +Peter Deacon +Gilles Dando +Philippe Desrichard +Jón Haase +Michael Hansen +Sylvain Vanston +Helmut Nemecek +Alexander Mathis +Jay Watkins +Patrice Oudjaoudi +Didier Hochedez +Robert Hunter +Christophe Gilsoul +Lincoln Roberts +Johan Jurriens +Michael Ledward +Dave Waldesbuehl +Dale Rhoads +Denis Kelly +SBEurope LTD +Jean-Louis Mouche +Grant Mills +Fernando Rimoldi +Jim Cukla +Tomas Kirnak +Raymond Henderson +James Jewitt +Martin Sauter +Philip Hawkey +Lonnie Misner +Michael Hirschauer +Brian Bracken +Stuart Olson +Terry McKinley +Miklos Turcsin +Edward Skerness +Stefano Perinetti +Toni Marchante diff --git a/cmake/FindFox.cmake b/cmake/FindFox.cmake index 1100c710d..9d76b61b0 100644 --- a/cmake/FindFox.cmake +++ b/cmake/FindFox.cmake @@ -56,7 +56,7 @@ else() set(FOX_LIBRARIES ${FOX_LIBRARY}) endif() -find_package_handle_standard_args(FOX +find_package_handle_standard_args(Fox DEFAULT_MSG FOX_INCLUDE_DIR FOX_LIBRARY diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index ca278494f..7e0b62da0 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -24,8 +24,6 @@ set(COMPANION_OSX_APP_BUNDLE_NAME "OpenTX Companion ${VERSION_MAJOR}.${VERSION_M # On OS X we copy dfu-util to the application bundle. This the path from which we copy # the binary (default homebrew path) set(DFU_UTIL_PATH "/usr/local/bin/dfu-util") -set(AVRDUDE_PATH "/usr/local/bin/avrdude") -set(AVRDUDE_CONF "/usr/local/etc/avrdude.conf") option(ALLOW_NIGHTLY_BUILDS "Allow nightly builds download / update") # Disabled by default if(ALLOW_NIGHTLY_BUILDS) @@ -239,7 +237,6 @@ set(companion_SRCS flasheepromdialog.cpp printdialog.cpp modelprinter.cpp - fusesdialog.cpp logsdialog.cpp downloaddialog.cpp splashlibrarydialog.cpp @@ -259,7 +256,6 @@ set(companion_MOC_HDRS burnconfigdialog.h comparedialog.h printdialog.h - fusesdialog.h logsdialog.h creditsdialog.h releasenotesdialog.h @@ -291,7 +287,6 @@ set(companion_MOC_HDRS set(companion_UIS mdichild.ui comparedialog.ui - fusesdialog.ui logsdialog.ui apppreferencesdialog.ui fwpreferencesdialog.ui @@ -356,6 +351,8 @@ elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T16) set(FLAVOUR t16) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL TX16S) set(FLAVOUR tx16s) +elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18) + set(FLAVOUR t18) else() string(TOLOWER ${PCB} FLAVOUR) endif() @@ -406,7 +403,7 @@ elseif(WIN32) install(TARGETS ${SIMULATOR_NAME} DESTINATION ${INSTALL_DESTINATION}) install(FILES ${simulator_plugins} DESTINATION "${INSTALL_DESTINATION}") # supporting utilities - set(INSTALL_TEMP_FILES avrdude.exe avrdude.conf dfu-util.exe libusb0.dll libusb-1.0.dll license.txt) + set(INSTALL_TEMP_FILES dfu-util.exe libusb0.dll libusb-1.0.dll license.txt) foreach(tmpfile ${INSTALL_TEMP_FILES}) install(FILES "${COMPANION_SRC_DIRECTORY}/../targets/windows/${tmpfile}" DESTINATION ${INSTALL_DESTINATION}) endforeach() @@ -552,14 +549,11 @@ IF(APPLE) set(${COMPANION_SOURCES} ${COMPANION_SOURCES} ${PROJECT_SOURCE_DIR}/images/${MACOSX_BUNDLE_ICON_FILE}) install(FILES ${MAC_ICON_FILE} DESTINATION ${companion_res_dir} COMPONENT Runtime) - # Copy dfu-util and avrdude, resolve symlink first + # Copy dfu-util, resolve symlink first get_filename_component(DFU_UTIL_ABSOLUTE_PATH ${DFU_UTIL_PATH} REALPATH) - get_filename_component(AVRDUDE_ABSOLUTE_PATH ${AVRDUDE_PATH} REALPATH) - get_filename_component(AVRDUDECONF_ABSOLUTE_PATH ${AVRDUDE_CONF} REALPATH) - install(PROGRAMS ${DFU_UTIL_ABSOLUTE_PATH} ${AVRDUDE_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime) - install(FILES ${AVRDUDECONF_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime) + install(PROGRAMS ${DFU_UTIL_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime) - set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/avrdude") + set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;") # Include depencies (adding frameworks, fixing the embbeded libraries) diff --git a/companion/src/burnconfigdialog.cpp b/companion/src/burnconfigdialog.cpp index 0fe22be03..43a60c7ea 100644 --- a/companion/src/burnconfigdialog.cpp +++ b/companion/src/burnconfigdialog.cpp @@ -36,61 +36,23 @@ burnConfigDialog::burnConfigDialog(QWidget *parent) : { ui->setupUi(this); setWindowIcon(CompanionIcon("configure.png")); - ui->avrdude_programmer->model()->sort(0); getSettings(); - populateProgrammers(); Board::Type board = getCurrentBoard(); if (IS_STM32(board)) { setWindowTitle(tr("DFU-UTIL Configuration")); - ui->avrArgs->hide(); - ui->avrdude_location->hide(); - ui->avrdude_port->hide(); - ui->avrdude_programmer->hide(); - ui->label_av1->hide(); - ui->label_av2->hide(); - ui->label_av4->hide(); - ui->label_av5->hide(); - ui->pushButton->hide(); - ui->pushButton_3->hide(); - ui->pushButton_4->hide(); ui->label_sb1->hide(); ui->label_sb3->hide(); ui->samba_location->hide(); ui->samba_port->hide(); ui->sb_browse->hide(); } - else if (IS_SKY9X(board)) { - setWindowTitle(tr("SAM-BA Configuration")); - ui->avrArgs->hide(); - ui->avrdude_location->hide(); - ui->avrdude_port->hide(); - ui->avrdude_programmer->hide(); - ui->label_av1->hide(); - ui->label_av2->hide(); - ui->label_av4->hide(); - ui->label_av5->hide(); - ui->pushButton->hide(); - ui->pushButton_3->hide(); - ui->pushButton_4->hide(); - ui->label_dfu1->hide(); - ui->dfu_location->hide(); - ui->dfu_browse->hide(); - } else { - setWindowTitle(tr("AVRDUDE Configuration")); - ui->label_sb1->hide(); - ui->label_sb3->hide(); - ui->samba_location->hide(); - ui->samba_port->hide(); - ui->sb_browse->hide(); + setWindowTitle(tr("SAM-BA Configuration")); ui->label_dfu1->hide(); - ui->label_dfu2->hide(); ui->dfu_location->hide(); ui->dfu_browse->hide(); } - ui->label_av3->hide(); - ui->avrdude_mcu->hide(); ui->label_sb2->hide(); ui->arm_mcu->hide(); ui->label_dfu2->hide(); @@ -105,46 +67,26 @@ burnConfigDialog::~burnConfigDialog() delete ui; } -QStringList burnConfigDialog::getAvrdudeArgs() -{ - QStringList args = avrArgs; - if (!avrPort.isEmpty()) - args << "-P" << avrPort; - -#if defined(__APPLE__) - args << "-C" << QFileInfo(QApplication::applicationDirPath() + "/../Resources/avrdude.conf").absoluteFilePath(); -#endif - return args; -} void burnConfigDialog::getSettings() { - avrLoc = g.avrdudeLocation(); sambaLoc = g.sambaLocation(); dfuLoc = g.dfuLocation(); #if defined WIN32 || !defined __GNUC__ - if ( avrLoc.isEmpty()) - avrLoc = QFileInfo("avrdude.exe").absoluteFilePath(); if ( sambaLoc.isEmpty()) sambaLoc = QFileInfo("sam-ba.exe").absoluteFilePath(); if ( dfuLoc.isEmpty()) dfuLoc = QFileInfo("dfu-util.exe").absoluteFilePath(); #elif defined __APPLE__ - if ( avrLoc.isEmpty()) - avrLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/avrdude").absoluteFilePath(); if ( sambaLoc.isEmpty()) sambaLoc = "/usr/local/bin/sam-ba"; if ( dfuLoc.isEmpty()) dfuLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/dfu-util").absoluteFilePath(); #elif defined __FreeBSD__ - if (avrLoc.isEmpty()) - avrLoc = "/usr/local/bin/avrdude"; if (dfuLoc.isEmpty()) dfuLoc = "/usr/local/bin/dfu-util"; #else - if ( avrLoc.isEmpty()) - avrLoc = "/usr/bin/avrdude"; if ( sambaLoc.isEmpty()) sambaLoc = "/usr/bin/sam-ba"; if ( dfuLoc.isEmpty()) @@ -152,45 +94,22 @@ void burnConfigDialog::getSettings() #endif dfuArgs = g.dfuArguments().split(" ", QString::SkipEmptyParts); - avrArgs = g.avrArguments().split(" ", QString::SkipEmptyParts); - avrProgrammer = g.programmer(); - avrPort = g.avrPort(); - avrMCU = g.mcu(); armMCU = g.armMcu(); sambaPort = g.sambaPort(); - ui->avrdude_location->setText(getAVRDUDE()); - ui->avrArgs->setText(avrArgs.join(" ")); - ui->samba_location->setText(getSAMBA()); ui->samba_port->setText(getSambaPort()); ui->dfu_location->setText(getDFU()); ui->dfuArgs->setText(getDFUArgs().join(" ")); - int idx1 = ui->avrdude_programmer->findText(getProgrammer()); - int idx2 = ui->avrdude_port->findText(getPort()); - int idx3 = ui->avrdude_mcu->findText(getMCU()); int idx4 = ui->arm_mcu->findText(getArmMCU()); - if(idx1>=0) ui->avrdude_programmer->setCurrentIndex(idx1); - if(idx2>=0) ui->avrdude_port->setCurrentIndex(idx2); - if(idx3>=0) ui->avrdude_mcu->setCurrentIndex(idx3); if(idx4>=0) ui->arm_mcu->setCurrentIndex(idx4); QFile file; - if (file.exists(avrLoc)) { - ui->pushButton_3->setEnabled(true); - } else { - ui->pushButton_3->setDisabled(true); - } } void burnConfigDialog::putSettings() { - g.avrdudeLocation( avrLoc ); - g.programmer( avrProgrammer); - g.mcu( avrMCU ); - g.avrPort( avrPort ); - g.avrArguments( avrArgs.join(" ") ); g.sambaLocation( sambaLoc ); g.sambaPort( sambaPort ); g.armMcu( armMCU ); @@ -198,73 +117,6 @@ void burnConfigDialog::putSettings() g.dfuArguments( dfuArgs.join(" ") ); } -void burnConfigDialog::populateProgrammers() -{ - QString fileName = QFileInfo(avrLoc).canonicalPath() + "/avrdude.conf"; //for windows - if(!QFileInfo(fileName).exists()) fileName = "/etc/avrdude.conf"; //for linux - if(!QFileInfo(fileName).exists()) fileName = "/etc/avrdude/avrdude.conf"; //for linux - if(!QFileInfo(fileName).exists()) return; // not found avrdude.conf - returning - - QFile file(fileName); - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; - - QStringList items; - QString line = ""; - QString prevline = ""; - QTextStream in(&file); - while (!in.atEnd()) - { - prevline = line; - line = in.readLine(); - - if(prevline.left(10).toLower()=="programmer") - items << line.section('"',1,1); - } - file.close(); - - items.sort(); - - QString avrProgrammer_temp = avrProgrammer; - ui->avrdude_programmer->clear(); - ui->avrdude_programmer->addItems(items); - int idx1 = ui->avrdude_programmer->findText(avrProgrammer_temp); - if(idx1>=0) ui->avrdude_programmer->setCurrentIndex(idx1); -} - -void burnConfigDialog::on_avrdude_programmer_currentIndexChanged(QString ) -{ - avrProgrammer = ui->avrdude_programmer->currentText(); -} - -void burnConfigDialog::on_avrdude_mcu_currentIndexChanged(QString ) -{ - avrMCU = ui->avrdude_mcu->currentText(); -} - -void burnConfigDialog::on_avrdude_location_editingFinished() -{ - avrLoc = ui->avrdude_location->text(); - if (avrLoc.isEmpty()) { - ui->pushButton_3->setDisabled(true); - } else { - QFile file; - if (file.exists(avrLoc)) { - ui->pushButton_3->setEnabled(true); - } - } -} - -void burnConfigDialog::on_avrArgs_editingFinished() -{ - avrArgs = ui->avrArgs->text().split(" ", QString::SkipEmptyParts); -} - -void burnConfigDialog::on_avrdude_port_currentIndexChanged(QString ) -{ - avrPort = ui->avrdude_port->currentText(); -} - void burnConfigDialog::on_samba_location_editingFinished() { sambaLoc = ui->samba_location->text(); @@ -280,17 +132,6 @@ void burnConfigDialog::on_arm_mcu_currentIndexChanged(QString ) armMCU = ui->arm_mcu->currentText(); } -void burnConfigDialog::on_pushButton_clicked() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Select Location"),ui->avrdude_location->text()); - - if(!fileName.isEmpty()) - { - ui->avrdude_location->setText(fileName); - avrLoc = fileName; - } -} - void burnConfigDialog::on_sb_browse_clicked() { QString fileName = QFileDialog::getOpenFileName(this, tr("Select Location"),ui->samba_location->text()); @@ -322,27 +163,6 @@ void burnConfigDialog::on_dfuArgs_editingFinished() dfuArgs = ui->dfuArgs->text().split(" ", QString::SkipEmptyParts); } -void burnConfigDialog::listAvrdudeProgrammers() -{ - ProgressDialog progressDialog(this, tr("List available programmers"), CompanionIcon("list.png"), true); - FlashProcess flashProcess(ui->avrdude_location->text(), QStringList() << "-c?", progressDialog.progress()); - flashProcess.run(); -} - -// TODO choose better name when no merge in progress.... -void burnConfigDialog::on_pushButton_3_clicked() -{ - listAvrdudeProgrammers(); -} - -// TODO choose better name when no merge in progress.... -void burnConfigDialog::on_pushButton_4_clicked() -{ - ProgressDialog progressDialog(this, tr("Avrdude help"), CompanionIcon("configure.png"), true); - FlashProcess flashProcess(ui->avrdude_location->text(), QStringList() << "-?", progressDialog.progress()); - flashProcess.run(); -} - void burnConfigDialog::on_advCtrChkB_toggled(bool checked) { Board::Type board = getCurrentBoard(); @@ -351,31 +171,20 @@ void burnConfigDialog::on_advCtrChkB_toggled(bool checked) ui->label_dfu2->show(); ui->dfuArgs->show(); } - else if (IS_SKY9X(board)) { + else { ui->label_sb2->show(); ui->arm_mcu->show(); } - else { - ui->label_av3->show(); - ui->avrdude_mcu->show(); - QMessageBox::warning(this, CPN_STR_APP_NAME, - tr("WARNING!
Normally CPU type is automatically selected according to the chosen firmware.
If you change the CPU type the resulting eeprom could be inconsistent."), - QMessageBox::Ok); - } } else { if (IS_STM32(board)) { ui->label_dfu2->hide(); ui->dfuArgs->hide(); } - else if (IS_SKY9X(board)) { + else { ui->label_sb2->hide(); ui->arm_mcu->hide(); } - else { - ui->label_av3->hide(); - ui->avrdude_mcu->hide(); - } } QTimer::singleShot(0, this, SLOT(shrink())); } diff --git a/companion/src/burnconfigdialog.h b/companion/src/burnconfigdialog.h index 5cf7bb375..06810bbd2 100644 --- a/companion/src/burnconfigdialog.h +++ b/companion/src/burnconfigdialog.h @@ -39,45 +39,25 @@ public: burnConfigDialog(QWidget *parent = 0); ~burnConfigDialog(); - QString getAVRDUDE() {return avrLoc;} QString getSAMBA() {return sambaLoc;} QString getDFU() {return dfuLoc;} - QStringList getAvrdudeArgs(); QStringList getDFUArgs() {return dfuArgs;} - QString getProgrammer() {return avrProgrammer;} - QString getMCU() {return avrMCU;} QString getArmMCU() {return armMCU;} - QString getPort() {return avrPort;} QString getSambaPort() {return sambaPort;} - void listAvrdudeProgrammers(); - private: Ui::burnConfigDialog *ui; void populateProgrammers(); - QString avrLoc; QString sambaLoc; QString dfuLoc; - QStringList avrArgs; - QString avrProgrammer; - QString avrMCU; QString armMCU; - QString avrPort; QString sambaPort; QStringList dfuArgs; private slots: void shrink(); - void on_avrArgs_editingFinished(); - void on_pushButton_4_clicked(); - void on_pushButton_3_clicked(); - void on_pushButton_clicked(); - void on_avrdude_location_editingFinished(); - void on_avrdude_programmer_currentIndexChanged(QString ); - void on_avrdude_mcu_currentIndexChanged(QString ); - void on_avrdude_port_currentIndexChanged(QString ); void on_samba_location_editingFinished(); void on_samba_port_editingFinished(); void on_arm_mcu_currentIndexChanged(QString ); diff --git a/companion/src/burnconfigdialog.ui b/companion/src/burnconfigdialog.ui index 36d343884..e52aaf797 100644 --- a/companion/src/burnconfigdialog.ui +++ b/companion/src/burnconfigdialog.ui @@ -45,615 +45,7 @@ - - - - Location of sam-ba executable - - - The location of the AVRDUDE executable. - - - dfu-util - - - - - - - DFU-Util Location - - - - - - - Location of AVRDUDE executable - - - The location of the AVRDUDE executable. - - - - - - - - - - Use this button to browse and look for the AVRDUDE executable file. - - - Browse... - - - - - - - Programmer - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Programmer used for communicating with the controller. -Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer. - - - QComboBox::InsertAlphabetically - - - - c2n232i - - - - - dasa3 - - - - - dasa - - - - - siprog - - - - - ponyser - - - - - 89isp - - - - - frank-stk200 - - - - - blaster - - - - - ere-isp-avr - - - - - atisp - - - - - dapa - - - - - xil - - - - - futurlec - - - - - abcmini - - - - - picoweb - - - - - sp12 - - - - - alf - - - - - bascom - - - - - dt006 - - - - - pony-stk200 - - - - - stk200 - - - - - bsd - - - - - pavr - - - - - dragon_pdi - - - - - dragon_dw - - - - - dragon_hvsp - - - - - dragon_pp - - - - - dragon_isp - - - - - dragon_jtag - - - - - jtag2pdi - - - - - jtag2avr32 - - - - - jtagmkII_avr32 - - - - - jtag2dw - - - - - jtag2isp - - - - - jtag2 - - - - - jtag2fast - - - - - jtag2slow - - - - - jtagmkII - - - - - jtag1slow - - - - - jtag1 - - - - - jtagmkI - - - - - avr911 - - - - - avr109 - - - - - butterfly - - - - - usbtiny - - - - - usbasp - - - - - avr910 - - - - - stk600hvsp - - - - - stk600pp - - - - - stk600 - - - - - stk500hvsp - - - - - stk500pp - - - - - stk500v2 - - - - - mib510 - - - - - stk500v1 - - - - - stk500 - - - - - buspirate - - - - - avrisp2 - - - - - avrispmkII - - - - - avrispv2 - - - - - avrisp - - - - - arduino - - - - - - - - List all available programmers. - - - List Available - - - - - - - Extra arguments that will be passed to AVRDUDE on every call - - - Extra arguments used in AVRDUDE. -This can be used for providing extra information to AVRDUDE. - -Please only use this if you know what you are doing. There are no error checks and you could cripple your controller. - - - - - - - - - - Extra Arguments - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Show AVRDUDE help - - - Show Help - - - - - - - Communication port to the programmer. - - - - - - - - - - usb - - - - - com1 - - - - - com2 - - - - - com3 - - - - - com4 - - - - - com5 - - - - - com6 - - - - - com7 - - - - - com8 - - - - - com9 - - - - - com10 - - - - - com11 - - - - - com12 - - - - - com13 - - - - - com14 - - - - - com15 - - - - - lpt1 - - - - - lpt2 - - - - - lpt3 - - - - - lpt4 - - - - - avrdoper - - - - - /dev/ttyUSB0 - - - - - /dev/ttyUSB1 - - - - - - - - Port - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - AVRDUDE Location - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - MCU - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - CPU of your TX - - - CPU present on your 9x radio -Should be m64 for stock radios -m2560 for v4.1 boards - - - QComboBox::InsertAlphabetically - - - - m64 - - - - - m128 - - - - - m2560 - - - - - + CPU of your TX @@ -678,7 +70,27 @@ m2560 for v4.1 boards - + + + + Location of sam-ba executable + + + The location of the AVRDUDE executable. + + + dfu-util + + + + + + + DFU-Util Location + + + + SAM-BA Location @@ -688,7 +100,7 @@ m2560 for v4.1 boards - + Location of sam-ba executable @@ -701,7 +113,7 @@ m2560 for v4.1 boards - + ARM MCU @@ -711,7 +123,7 @@ m2560 for v4.1 boards - + Port @@ -721,7 +133,7 @@ m2560 for v4.1 boards - + sam-ba serial port @@ -734,14 +146,14 @@ m2560 for v4.1 boards - + Alternate device - + Extra arguments that will be passed to AVRDUDE on every call @@ -757,7 +169,7 @@ Please only use this if you know what you are doing. There are no error checks - + Use this button to browse and look for the AVRDUDE executable file. @@ -767,7 +179,7 @@ Please only use this if you know what you are doing. There are no error checks - + Use this button to browse and look for the AVRDUDE executable file. @@ -777,14 +189,14 @@ Please only use this if you know what you are doing. There are no error checks - + - + Use advanced controls @@ -809,14 +221,6 @@ Please only use this if you know what you are doing. There are no error checks - avrdude_location - pushButton - avrdude_programmer - pushButton_3 - avrdude_mcu - avrdude_port - avrArgs - pushButton_4 samba_location sb_browse arm_mcu diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index ce172fbb7..cddc2fa3e 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -190,6 +190,16 @@ images/simulator/JumperT16/left_tele.png images/simulator/JumperT16/right_ent.png images/simulator/JumperT16/right_rtn.png + images/simulator/JumperT18/left.png + images/simulator/JumperT18/right.png + images/simulator/JumperT18/top.png + images/simulator/JumperT18/bottom.png + images/simulator/JumperT18/left_mdl.png + images/simulator/JumperT18/left_page.png + images/simulator/JumperT18/left_sys.png + images/simulator/JumperT18/left_tele.png + images/simulator/JumperT18/right_ent.png + images/simulator/JumperT18/right_rtn.png images/simulator/TX16S/left.png images/simulator/TX16S/right.png images/simulator/TX16S/top.png diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt index 502a04961..1b99964fa 100644 --- a/companion/src/firmwares/CMakeLists.txt +++ b/companion/src/firmwares/CMakeLists.txt @@ -18,8 +18,7 @@ set(firmwares_SRCS rawswitch.cpp sensordata.cpp telem_data.cpp - er9x/er9xeeprom.cpp - er9x/er9xinterface.cpp + afhds3.cpp ersky9x/ersky9xeeprom.cpp ersky9x/ersky9xinterface.cpp opentx/opentxeeprom.cpp diff --git a/companion/src/firmwares/afhds3.cpp b/companion/src/firmwares/afhds3.cpp new file mode 100644 index 000000000..000fb252c --- /dev/null +++ b/companion/src/firmwares/afhds3.cpp @@ -0,0 +1,12 @@ +#include "afhds3.h" +#include "macros.h" + +QString Afhds3Data::protocolToString(unsigned int protocol) { + const char * const afhds3Protocols[] = { + "PWM/IBUS", + "PWM/SBUS", + "PPM/IBUS", + "PPM/SBUS", + }; + return CHECK_IN_ARRAY(afhds3Protocols, protocol); +} diff --git a/companion/src/firmwares/afhds3.h b/companion/src/firmwares/afhds3.h new file mode 100644 index 000000000..ea4257fba --- /dev/null +++ b/companion/src/firmwares/afhds3.h @@ -0,0 +1,12 @@ +#ifndef AFHDS3_H +#define AFHDS3_H + +#include + +class Afhds3Data +{ + Q_DECLARE_TR_FUNCTIONS(Afhds3) +public: + static QString protocolToString(unsigned int protocol); +}; +#endif // AFHDS3_H diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index cfadf5936..5e0ceeb86 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -25,18 +25,13 @@ // Update: These are now all only used within this class. // External access is only via getEEpromSize() and getFlashSize() -#define EESIZE_STOCK 2048 -#define EESIZE_M128 4096 -#define EESIZE_GRUVIN9X 4096 #define EESIZE_TARANIS (32*1024) #define EESIZE_SKY9X (128*4096) #define EESIZE_9XRPRO (128*4096) #define EESIZE_MAX EESIZE_9XRPRO // getFlashSize() (and these macros) is only used by radiointerface::getDfuArgs (perhaps can find a better way?) -#define FSIZE_STOCK (64*1024) -#define FSIZE_M128 (128*1024) -#define FSIZE_GRUVIN9X (256*1024) + #define FSIZE_TARANIS (512*1024) #define FSIZE_SKY9X (256*1024) #define FSIZE_9XRPRO (512*1024) @@ -82,16 +77,12 @@ uint32_t Boards::getFourCC(Type board) case BOARD_AR9X: case BOARD_9XRPRO: return 0x3278746F; - case BOARD_MEGA2560: - case BOARD_GRUVIN9X: - return 0x3178746F; - case BOARD_9X_M64: - case BOARD_9X_M128: - return 0; case BOARD_JUMPER_T12: return 0x3D78746F; case BOARD_JUMPER_T16: return 0x3F78746F; + case BOARD_JUMPER_T18: + return 0x4078746F; case BOARD_RADIOMASTER_TX16S: return 0x3878746F; case BOARD_UNKNOWN: @@ -104,13 +95,6 @@ uint32_t Boards::getFourCC(Type board) int Boards::getEEpromSize(Board::Type board) { switch (board) { - case BOARD_9X_M64: - return EESIZE_STOCK; - case BOARD_9X_M128: - return EESIZE_M128; - case BOARD_MEGA2560: - case BOARD_GRUVIN9X: - return EESIZE_GRUVIN9X; case BOARD_SKY9X: return EESIZE_SKY9X; case BOARD_9XRPRO: @@ -134,6 +118,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_X10: case BOARD_X10_EXPRESS: case BOARD_JUMPER_T16: + case BOARD_JUMPER_T18: case BOARD_RADIOMASTER_TX16S: return 0; } @@ -144,13 +129,6 @@ int Boards::getEEpromSize(Board::Type board) int Boards::getFlashSize(Type board) { switch (board) { - case BOARD_9X_M64: - return FSIZE_STOCK; - case BOARD_9X_M128: - return FSIZE_M128; - case BOARD_MEGA2560: - case BOARD_GRUVIN9X: - return FSIZE_GRUVIN9X; case BOARD_SKY9X: return FSIZE_SKY9X; case BOARD_9XRPRO: @@ -172,6 +150,7 @@ int Boards::getFlashSize(Type board) case BOARD_X10: case BOARD_X10_EXPRESS: case BOARD_JUMPER_T16: + case BOARD_JUMPER_T18: case BOARD_RADIOMASTER_TX16S: return FSIZE_HORUS; case BOARD_UNKNOWN: @@ -310,7 +289,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 0; case MouseAnalogs: - if (IS_FAMILY_HORUS_OR_T16(board)) + if (IS_HORUS_X12S(board)) return 2; else return 0; @@ -412,7 +391,7 @@ QString Boards::getAnalogInputName(Board::Type board, int index) index -= getCapability(board, Board::Sticks); - if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) { + if (IS_SKY9X(board)) { const QString pots[] = { "P1", "P2", @@ -496,14 +475,6 @@ bool Boards::isBoardCompatible(Type board1, Type board2) QString Boards::getBoardName(Board::Type board) { switch (board) { - case BOARD_9X_M64: - return "9X"; - case BOARD_9X_M128: - return "9X128"; - case BOARD_GRUVIN9X: - return "Gruvin9x"; - case BOARD_MEGA2560: - return "MEGA2560"; case BOARD_TARANIS_X7: return "Taranis X7/X7S"; case BOARD_TARANIS_X7_ACCESS: @@ -540,6 +511,8 @@ QString Boards::getBoardName(Board::Type board) return "Horus X10/X10S Express"; case BOARD_JUMPER_T16: return "Jumper T16"; + case BOARD_JUMPER_T18: + return "Jumper T18"; case BOARD_RADIOMASTER_TX16S: return "Radiomaster TX16S"; default: diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index e4149a298..2ecf3c2fe 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -32,10 +32,6 @@ namespace Board { enum Type { BOARD_UNKNOWN = -1, - BOARD_9X_M64 = 0, - BOARD_9X_M128, - BOARD_MEGA2560, - BOARD_GRUVIN9X, BOARD_SKY9X, BOARD_9XRPRO, BOARD_AR9X, @@ -55,9 +51,10 @@ namespace Board { BOARD_JUMPER_T12, BOARD_JUMPER_T16, BOARD_RADIOMASTER_TX16S, + BOARD_JUMPER_T18, }; - constexpr int BOARD_TYPE_MAX = BOARD_RADIOMASTER_TX16S ; + constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T18; enum PotType { @@ -191,26 +188,6 @@ class Boards // temporary aliases for transition period, use Boards class instead. #define getBoardCapability(b__, c__) Boards::getCapability(b__, c__) -inline bool IS_9X(Board::Type board) -{ - return board == Board::BOARD_9X_M64 || board == Board::BOARD_9X_M128; -} - -inline bool IS_STOCK(Board::Type board) -{ - return board == Board::BOARD_9X_M64; -} - -inline bool IS_M128(Board::Type board) -{ - return board == Board::BOARD_9X_M128; -} - -inline bool IS_2560(Board::Type board) -{ - return board == Board::BOARD_GRUVIN9X || board == Board::BOARD_MEGA2560; -} - inline bool IS_SKY9X(Board::Type board) { return board == Board::BOARD_SKY9X || board == Board::BOARD_9XRPRO || board == Board::BOARD_AR9X; @@ -231,6 +208,11 @@ inline bool IS_JUMPER_T16(Board::Type board) return board == Board::BOARD_JUMPER_T16; } +inline bool IS_JUMPER_T18(Board::Type board) +{ + return board == Board::BOARD_JUMPER_T18; +} + inline bool IS_RADIOMASTER_TX16S(Board::Type board) { return board == Board::BOARD_RADIOMASTER_TX16S; @@ -238,7 +220,7 @@ inline bool IS_RADIOMASTER_TX16S(Board::Type board) inline bool IS_FAMILY_T16(Board::Type board) { - return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S; + return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18; } inline bool IS_TARANIS_XLITE(Board::Type board) @@ -346,7 +328,12 @@ inline bool HAS_EXTERNAL_ANTENNA(Board::Type board) return (board == Board::BOARD_X10 || board == Board::BOARD_HORUS_X12S || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))); } -inline bool IS_ACCESS_RADIO(Board::Type board, QString &id) +inline bool IS_TARANIS_X9DP_2019(Board::Type board) +{ + return (board == Board::BOARD_TARANIS_X9DP_2019); +} + +inline bool IS_ACCESS_RADIO(Board::Type board, const QString & id) { return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == Board::BOARD_TARANIS_X9DP_2019 || board == Board::BOARD_X10_EXPRESS || IS_TARANIS_X7_ACCESS(board) || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess"))); diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp index 9313ace5a..42d84d570 100644 --- a/companion/src/firmwares/customfunctiondata.cpp +++ b/companion/src/firmwares/customfunctiondata.cpp @@ -46,7 +46,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model)); else if (func == FuncTrainer) - return tr("Trainer"); + return tr("Trainer Sticks"); else if (func == FuncTrainerRUD) return tr("Trainer RUD"); else if (func == FuncTrainerELE) @@ -112,13 +112,10 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox { int val = 0; Firmware * firmware = Firmware::getCurrentVariant(); - Board::Type board = firmware->getBoard(); b->addItem(tr("Timer1"), val++); b->addItem(tr("Timer2"), val++); - if (IS_ARM(board)) { - b->addItem( tr("Timer3"), val++); - } + b->addItem( tr("Timer3"), val++); b->addItem(tr("Flight"), val++); b->addItem(tr("Telemetry"), val++); int reCount = firmware->getCapability(RotaryEncoders); @@ -132,7 +129,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox if ((int)value < b->count()) { b->setCurrentIndex(value); } - if (model && IS_ARM(board)) { + if (model) { for (unsigned i=0; isensorData[i].isAvailable()) { RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i); @@ -162,24 +159,24 @@ QString CustomFunctionData::paramToString(const ModelData * model) const if (func <= FuncInstantTrim) { return QString("%1").arg(param); } - else if (func==FuncLogs) { + else if (func == FuncLogs) { return QString("%1").arg(param/10.0) + tr("s"); } - else if (func==FuncPlaySound) { + else if (func == FuncPlaySound) { CustomFunctionData::populatePlaySoundParams(qs); if (param>=0 && param<(int)qs.count()) return qs.at(param); else return tr("Inconsistent parameter"); } - else if (func==FuncPlayHaptic) { + else if (func == FuncPlayHaptic) { CustomFunctionData::populateHapticParams(qs); if (param>=0 && param<(int)qs.count()) return qs.at(param); else return tr("Inconsistent parameter"); } - else if (func==FuncReset) { + else if (func == FuncReset) { QComboBox cb; CustomFunctionData::populateResetParams(model, &cb); int pos = cb.findData(param); @@ -188,11 +185,11 @@ QString CustomFunctionData::paramToString(const ModelData * model) const else return tr("Inconsistent parameter"); } - else if ((func==FuncVolume)|| (func==FuncPlayValue)) { + else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) { RawSource item(param); return item.toString(model); } - else if ((func==FuncPlayPrompt) || (func==FuncPlayBoth)) { + else if (func == FuncPlayPrompt || func == FuncPlayBoth) { if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) { return QString("%1").arg(param); } @@ -200,7 +197,7 @@ QString CustomFunctionData::paramToString(const ModelData * model) const return paramarm; } } - else if ((func>=FuncAdjustGV1) && (func= FuncAdjustGV1 && func < FuncCount) { switch (adjustMode) { case FUNC_ADJUST_GVAR_CONSTANT: return tr("Value ")+QString("%1").arg(param); @@ -210,14 +207,8 @@ QString CustomFunctionData::paramToString(const ModelData * model) const case FUNC_ADJUST_GVAR_INCDEC: float val; QString unit; - if (IS_ARM(getCurrentBoard())) { - val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet(); - unit = model->gvarData[func - FuncAdjustGV1].unitToString(); - } - else { - val = param; - unit = ""; - } + val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet(); + unit = model->gvarData[func - FuncAdjustGV1].unitToString(); return QString("Increment: %1%2").arg(val).arg(unit); } } @@ -233,18 +224,19 @@ QString CustomFunctionData::repeatToString() const return ""; } else { - unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10; + unsigned int step = 1; return tr("repeat(%1s)").arg(step*repeatParam); } } QString CustomFunctionData::enabledToString() const { - if ((func>=FuncOverrideCH1 && func<=FuncOverrideCH32) || - (func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) || - (func==FuncReset) || - (func>=FuncSetTimer1 && func<=FuncSetTimer2) || - (func==FuncVolume) || + if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) || + (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) || + (func == FuncReset) || + (func >= FuncSetTimer1 && func <= FuncSetTimer2) || + (func == FuncVolume) || + (func == FuncBacklight) || (func <= FuncInstantTrim)) { if (!enabled) { return tr("DISABLED"); @@ -258,7 +250,7 @@ void CustomFunctionData::convert(RadioDataConversionState & cstate) cstate.setComponent(tr("CFN"), 8); cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true))); swtch.convert(cstate); - if (func == FuncVolume || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) { + if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) { param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue(); } } diff --git a/companion/src/firmwares/eeprominterface.cpp b/companion/src/firmwares/eeprominterface.cpp index d4121a8a4..90272d0ad 100644 --- a/companion/src/firmwares/eeprominterface.cpp +++ b/companion/src/firmwares/eeprominterface.cpp @@ -75,10 +75,7 @@ void EEPROMInterface::showEepromErrors(QWidget *parent, const QString &title, co if (errors.test(UNSUPPORTED_NEWER_VERSION)) { errorsList << tr("- Eeprom is from a newer version of OpenTX"); } if (errors.test(NOT_OPENTX)) { errorsList << tr("- Eeprom is not from OpenTX"); } - if (errors.test(NOT_TH9X)) { errorsList << tr("- Eeprom is not from Th9X"); } - if (errors.test(NOT_GRUVIN9X)) { errorsList << tr("- Eeprom is not from Gruvin9X"); } if (errors.test(NOT_ERSKY9X)) { errorsList << tr("- Eeprom is not from ErSky9X"); } - if (errors.test(NOT_ER9X)) { errorsList << tr("- Eeprom is not from Er9X"); } if (errors.test(WRONG_SIZE)) { errorsList << tr("- Eeprom size is invalid"); } if (errors.test(WRONG_FILE_SYSTEM)) { errorsList << tr("- Eeprom file system is invalid"); } if (errors.test(UNKNOWN_BOARD)) { errorsList << tr("- Eeprom is from a unknown board"); } diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h index c2bf0dafa..b3680b4ba 100644 --- a/companion/src/firmwares/eeprominterface.h +++ b/companion/src/firmwares/eeprominterface.h @@ -235,10 +235,7 @@ enum EepromLoadErrors { WRONG_SIZE, WRONG_FILE_SYSTEM, NOT_OPENTX, - NOT_TH9X, - NOT_GRUVIN9X, NOT_ERSKY9X, - NOT_ER9X, UNKNOWN_BOARD, WRONG_BOARD, BACKUP_NOT_SUPPORTED, diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index 9c38391c7..f307dbf26 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -110,9 +110,7 @@ GeneralSettings::GeneralSettings() backlightOffBright = 20; } - if (IS_ARM(board)) { - speakerVolume = 12; - } + speakerVolume = 12; if (IS_JUMPER_T16(board)) strcpy(bluetoothName, "t16"); diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index a111cac1e..cdb72d9c8 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -142,6 +142,7 @@ class GeneralSettings { unsigned int countryCode; bool jitterFilter; bool rtcCheckDisable; + bool keysBacklight; unsigned int imperial; char ttsLanguage[2+1]; int beepVolume; diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 3386ba41d..e38958249 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -43,6 +43,11 @@ bool TimerData::isEmpty() return (mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0) && name[0] == '\0' && minuteBeep == 0 && countdownBeep == COUNTDOWN_SILENT && val == 0 && persistent == 0 /*&& pvalue == 0*/); } +QString TimerData::nameToString(int index) const +{ + return RadioData::getElementName(tr("TMR", "as in Timer"), index + 1, name); +} + /* * ModelData */ @@ -207,36 +212,25 @@ bool ModelData::isEmpty() const void ModelData::setDefaultInputs(const GeneralSettings & settings) { - Board::Type board = getCurrentBoard(); - if (IS_ARM(board)) { - for (int i = 0; i < CPN_MAX_STICKS; i++) { - ExpoData * expo = &expoData[i]; - expo->chn = i; - expo->mode = INPUT_MODE_BOTH; - expo->srcRaw = settings.getDefaultSource(i); - expo->weight = 100; - strncpy(inputNames[i], Helpers::removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i]) - 1); - } + for (int i = 0; i < CPN_MAX_STICKS; i++) { + ExpoData * expo = &expoData[i]; + expo->chn = i; + expo->mode = INPUT_MODE_BOTH; + expo->srcRaw = settings.getDefaultSource(i); + expo->weight = 100; + strncpy(inputNames[i], Helpers::removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i]) - 1); } } void ModelData::setDefaultMixes(const GeneralSettings & settings) { - Board::Type board = getCurrentBoard(); - if (IS_ARM(board)) { - setDefaultInputs(settings); - } + setDefaultInputs(settings); for (int i = 0; i < CPN_MAX_STICKS; i++) { MixData * mix = &mixData[i]; mix->destCh = i + 1; mix->weight = 100; - if (IS_ARM(board)) { - mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i); - } - else { - mix->srcRaw = RawSource(SOURCE_TYPE_STICK, i); - } + mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i); } } @@ -538,6 +532,8 @@ int ModelData::updateReference() Firmware *fw = getCurrentFirmware(); + updRefInfo.occurences = 1; + switch (updRefInfo.type) { case REF_UPD_TYPE_CHANNEL: @@ -572,6 +568,7 @@ int ModelData::updateReference() updRefInfo.srcType = SOURCE_TYPE_TELEMETRY; updRefInfo.swtchType = SWITCH_TYPE_SENSOR; updRefInfo.maxindex = fw->getCapability(Sensors); + updRefInfo.occurences = 3; break; case REF_UPD_TYPE_TIMER: updRefInfo.srcType = SOURCE_TYPE_SPECIAL; @@ -662,6 +659,8 @@ int ModelData::updateReference() } } } + if (updRefInfo.type == REF_UPD_TYPE_CHANNEL) + sortMixes(); //s1.report("Mixes"); for (int i = 0; i < CPN_MAX_CHNOUT; i++) { @@ -724,7 +723,7 @@ int ModelData::updateReference() updateAssignFunc(cfd); if (!cfd->isEmpty()) { updateSwitchRef(cfd->swtch); - if (cfd->func == FuncVolume || cfd->func == FuncPlayValue || (cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) { + if (cfd->func == FuncVolume || cfd->func == FuncBacklight || cfd->func == FuncPlayValue || (cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) { updateSourceIntRef(cfd->param); if (cfd->param == 0) cfd->clear(); @@ -773,15 +772,35 @@ int ModelData::updateReference() //s1.report("Telemetry"); } - // TODO maybe less risk to leave it up to the user?? - /* for (int i = 0; i < CPN_MAX_SENSORS; i++) { SensorData *sd = &sensorData[i]; - if (sd->isAvailable() && sd->type == SensorData::TELEM_TYPE_CALCULATED) { + if (!sd->isEmpty() && sd->type == SensorData::TELEM_TYPE_CALCULATED) { + if (sd->formula == SensorData::TELEM_FORMULA_CELL) { + updateTelemetryRef(sd->source); + if (sd->source == 0) { + sd->clear(); + appendUpdateReferenceParams(REF_UPD_TYPE_SENSOR, REF_UPD_ACT_CLEAR, i); + } + } + else if (sd->formula == SensorData::TELEM_FORMULA_DIST) { + updateTelemetryRef(sd->gps); + updateTelemetryRef(sd->alt); + } + else if (sd->formula == SensorData::TELEM_FORMULA_CONSUMPTION || sd->formula == SensorData::TELEM_FORMULA_TOTALIZE) { + updateTelemetryRef(sd->amps); + if (sd->amps == 0) { + sd->clear(); + appendUpdateReferenceParams(REF_UPD_TYPE_SENSOR, REF_UPD_ACT_CLEAR, i); + } + } + else { + for (unsigned int i = 0; i < 4; i++) { + updateTelemetryRef(sd->sources[i]); + } + } } } - s1.report("Telemetry Sensors"); - */ + //s1.report("Telemetry Sensors"); // TODO needs lua incorporated into Companion as script needs to be parsed to determine if input field is source or value /* @@ -817,38 +836,40 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c newRef.type = curRef.type; newRef.index = abs(curRef.index); + div_t idx = div(newRef.index, updRefInfo.occurences); + switch (updRefInfo.action) { case REF_UPD_ACT_CLEAR: - if (newRef.index != (updRefInfo.index1 + idxAdj)) + if (idx.quot != (updRefInfo.index1 + idxAdj)) return; if (defClear) newRef.clear(); else { newRef.type = (T)defType; - newRef.index = defIndex; + newRef.index = defIndex + idxAdj; } break; case REF_UPD_ACT_SHIFT: - if (newRef.index < (updRefInfo.index1 + idxAdj)) + if (idx.quot < (updRefInfo.index1 + idxAdj)) return; newRef.index += updRefInfo.shift; - if (newRef.index < (updRefInfo.index1 + idxAdj) || newRef.index > (updRefInfo.maxindex + idxAdj)) { + if (idx.quot < (updRefInfo.index1 + idxAdj) || idx.quot > (updRefInfo.maxindex + idxAdj)) { if (defClear) newRef.clear(); else { newRef.type = (T)defType; - newRef.index = defIndex; + newRef.index = defIndex + idxAdj; } } break; case REF_UPD_ACT_SWAP: - if (newRef.index == updRefInfo.index1 + idxAdj) - newRef.index = updRefInfo.index2 + idxAdj; - else if (newRef.index == updRefInfo.index2 + idxAdj) - newRef.index = updRefInfo.index1 + idxAdj; + if (idx.quot == updRefInfo.index1 + idxAdj) + newRef.index = ((updRefInfo.index2 + idxAdj) * updRefInfo.occurences) + idx.rem; + else if (idx.quot == updRefInfo.index2 + idxAdj) + newRef.index = ((updRefInfo.index1 + idxAdj) * updRefInfo.occurences) + idx.rem; break; default: qDebug() << "Error - unhandled action:" << updRefInfo.action; @@ -883,7 +904,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c newRef.clear(); else { newRef.type = (T)defType; - newRef.value = defValue; + newRef.value = defValue + idxAdj; } break; case REF_UPD_ACT_SHIFT: @@ -897,7 +918,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c newRef.clear(); else { newRef.type = (T)defType; - newRef.value = defValue; + newRef.value = defValue + idxAdj; } } break; @@ -1126,13 +1147,14 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef) } } -void ModelData::updateTelemetryRef(unsigned int & curRef) +void ModelData::updateTelemetryRef(int & curRef) { if (updRefInfo.type != REF_UPD_TYPE_SENSOR) return; const int idxAdj = 1; int newRef = curRef; + switch (updRefInfo.action) { case REF_UPD_ACT_CLEAR: @@ -1160,13 +1182,23 @@ void ModelData::updateTelemetryRef(unsigned int & curRef) return; } - if (curRef != static_cast(newRef)) { + if (curRef != newRef) { //qDebug() << "Updated reference:" << curRef << " -> " << newRef; curRef = newRef; updRefInfo.updcnt++; } } +void ModelData::updateTelemetryRef(unsigned int & curRef) +{ + int newRef = (int)curRef; + updateTelemetryRef(newRef); + + if (curRef != static_cast(newRef)) { + curRef = (unsigned int)newRef; + } +} + void ModelData::updateModuleFailsafes(ModuleData * md) { if (updRefInfo.type != REF_UPD_TYPE_CHANNEL) @@ -1300,3 +1332,45 @@ void ModelData::removeMix(const int idx) memmove(&mixData[idx], &mixData[idx + 1], (CPN_MAX_MIXERS - (idx + 1)) * sizeof(MixData)); mixData[CPN_MAX_MIXERS - 1].clear(); } + +void ModelData::sortMixes() +{ + unsigned int lastchn = 0; + bool sortreq = false; + + for (int i = 0; i < CPN_MAX_MIXERS; i++) { + MixData *md = &mixData[i]; + if (!md->isEmpty()) { + if (md->destCh < lastchn) { + sortreq = true; + break; + } + else + lastchn = md->destCh; + } + } + + if (!sortreq) + return; + + // QMap automatically sorts based on key + QMap map; + for (int i = 0; i < CPN_MAX_MIXERS; i++) { + MixData *md = &mixData[i]; + if (!md->isEmpty()) { + // destCh may not be unique so build a compound sort key + map.insert(md->destCh * (CPN_MAX_MIXERS + 1) + i, i); + } + } + + MixData sortedMixData[CPN_MAX_MIXERS]; + int destidx = 0; + + QMap::const_iterator i; + for (i = map.constBegin(); i != map.constEnd(); ++i) { + memcpy(&sortedMixData[destidx], &mixData[i.value()], sizeof(MixData)); + destidx++; + } + + memcpy(&mixData[0], &sortedMixData[0], CPN_MAX_MIXERS * sizeof(MixData)); +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 93e98588e..0afc66b72 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -41,13 +41,10 @@ class RadioDataConversionState; class RSSIAlarmData { public: RSSIAlarmData() { clear(); } - unsigned int level[2]; // AVR Only int warning; int critical; bool disabled; void clear() { - this->level[0] = 2; - this->level[1] = 3; this->warning = 45; this->critical = 42; this->disabled = false; @@ -78,6 +75,7 @@ class TimerData { void convert(RadioDataConversionState & cstate); bool isEmpty(); bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); } + QString nameToString(int index) const; }; #define CPN_MAX_SCRIPTS 9 @@ -184,6 +182,7 @@ class ModelData { unsigned int thrTraceSrc; uint64_t switchWarningStates; unsigned int switchWarningEnable; + unsigned int thrTrimSwitch; unsigned int potsWarningMode; bool potsWarnEnabled[CPN_MAX_POTS]; int potsWarnPosition[CPN_MAX_POTS]; @@ -300,6 +299,7 @@ class ModelData { int shift; int updcnt; int maxindex; + int occurences; RawSourceType srcType; RawSwitchType swtchType; }; @@ -317,6 +317,7 @@ class ModelData { void updateDestCh(MixData * md); void updateLimitCurveRef(CurveReference & crv); void updateFlightModeFlags(unsigned int & flags); + void updateTelemetryRef(int & idx); void updateTelemetryRef(unsigned int & idx); void updateModuleFailsafes(ModuleData * md); inline void updateSourceRef(RawSource & src) { updateTypeIndexRef(src, updRefInfo.srcType); } @@ -336,6 +337,7 @@ class ModelData { if (value != swtch.toValue()) value = swtch.toValue(); } + void sortMixes(); }; #endif // MODELDATA_H diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index 370a6979b..b36d88e04 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -21,6 +21,7 @@ #include "moduledata.h" #include "eeprominterface.h" #include "multiprotocols.h" +#include "afhds3.h" #include "radiodataconversionstate.h" void ModuleData::convert(RadioDataConversionState & cstate) @@ -65,6 +66,7 @@ bool ModuleData::supportRxNum() const case PULSES_PXX_R9M_LITE: case PULSES_PXX_R9M_LITE_PRO: case PULSES_MULTIMODULE: + case PULSES_CROSSFIRE: case PULSES_ACCESS_ISRM: case PULSES_ACCST_ISRM_D16: case PULSES_ACCESS_R9M: @@ -87,7 +89,6 @@ QString ModuleData::rfProtocolToString() const switch (protocol) { case PULSES_MULTIMODULE: return Multiprotocols::protocolToString((int)multi.rfProtocol); - default: return CPN_STR_UNKNOWN_ITEM; } @@ -108,10 +109,10 @@ QString ModuleData::subTypeToString(int type) const switch (protocol) { case PULSES_MULTIMODULE: return Multiprotocols::subTypeToString((int)multi.rfProtocol, (unsigned)type); - case PULSES_PXX_R9M: return CHECK_IN_ARRAY(strings, type); - + case PULSES_AFHDS3: + return Afhds3Data::protocolToString(type); default: return CPN_STR_UNKNOWN_ITEM; } @@ -119,8 +120,8 @@ QString ModuleData::subTypeToString(int type) const QString ModuleData::powerValueToString(Firmware * fw) const { - const QStringList & strRef = powerValueStrings(subType, fw); - return strRef.value(pxx.power, CPN_STR_UNKNOWN_ITEM); + const QStringList & strRef = powerValueStrings((enum PulsesProtocol)protocol, subType, fw); + return strRef.value(protocol == PULSES_AFHDS3 ? afhds3.rfPower : pxx.power, CPN_STR_UNKNOWN_ITEM); } // static @@ -159,14 +160,16 @@ QString ModuleData::protocolToString(unsigned protocol) "FrSky ACCESS R9M 2019", "FrSky ACCESS R9M Lite", "FrSky ACCESS R9M Lite Pro", - "FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)" + "FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)", + "AFHDS3", + "ImmersionRC Ghost" }; return CHECK_IN_ARRAY(strings, protocol); } // static -QStringList ModuleData::powerValueStrings(int subType, Firmware * fw) +QStringList ModuleData::powerValueStrings(enum PulsesProtocol protocol, int subType, Firmware * fw) { static const QStringList strings[] = { { tr("10mW - 16CH"), tr("100mW - 16CH"), tr("500mW - 16CH"), tr("Auto <= 1W - 16CH") }, // full-size FCC @@ -174,12 +177,21 @@ QStringList ModuleData::powerValueStrings(int subType, Firmware * fw) { tr("100mW - 16CH") }, // mini FCC { tr("25mW - 8CH"), tr("25mW - 16CH"), tr("100mW - 16CH (no telemetry)") } // mini EU }; - int strIdx = 0; - if (subType == MODULE_SUBTYPE_R9M_EU) - strIdx += 1; - if (fw->getCapability(HasModuleR9MMini)) - strIdx += 2; - return strings[strIdx]; + static const QStringList afhds3Strings = { + tr("25 mW"), tr("100 mW"), tr("500 mW"), tr("1 W"), tr("2 W") + }; + + switch(protocol) { + case PULSES_AFHDS3: + return afhds3Strings; + default: + int strIdx = 0; + if (subType == MODULE_SUBTYPE_R9M_EU) + strIdx += 1; + if (fw->getCapability(HasModuleR9MMini)) + strIdx += 2; + return strings[strIdx]; + } } bool ModuleData::hasFailsafes(Firmware * fw) const @@ -193,7 +205,8 @@ bool ModuleData::hasFailsafes(Firmware * fw) const protocol == PULSES_ACCESS_R9M_LITE || protocol == PULSES_ACCESS_R9M_LITE_PRO || protocol == PULSES_XJT_LITE_X16 || - protocol == PULSES_MULTIMODULE + protocol == PULSES_MULTIMODULE || + protocol == PULSES_AFHDS3 ); } @@ -210,6 +223,7 @@ int ModuleData::getMaxChannelCount() case PULSES_XJT_LITE_X16: case PULSES_PXX_XJT_X16: case PULSES_CROSSFIRE: + case PULSES_GHOST: case PULSES_SBUS: case PULSES_PPM: return 16; @@ -230,6 +244,8 @@ int ModuleData::getMaxChannelCount() else return 16; break; + case PULSES_AFHDS3: + return 18; case PULSES_OFF: break; default: diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index 86614b392..e22c167e3 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -58,6 +58,8 @@ enum PulsesProtocol { PULSES_XJT_LITE_X16, PULSES_XJT_LITE_D8, PULSES_XJT_LITE_LR12, + PULSES_AFHDS3, + PULSES_GHOST, PULSES_PROTOCOL_LAST }; @@ -190,6 +192,11 @@ class ModuleData { int optionValue; } multi; + struct Afhds3 { + unsigned int rxFreq; + unsigned int rfPower; + } afhds3; + struct PXX { unsigned int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W bool receiverTelemetryOff; // false = receiver telem enabled @@ -213,7 +220,7 @@ class ModuleData { QString powerValueToString(Firmware * fw) const; static QString indexToString(int index, Firmware * fw); static QString protocolToString(unsigned protocol); - static QStringList powerValueStrings(int subType, Firmware * fw); + static QStringList powerValueStrings(enum PulsesProtocol protocol, int subType, Firmware * fw); bool hasFailsafes(Firmware * fw) const; int getMaxChannelCount(); }; diff --git a/companion/src/firmwares/multiprotocols.cpp b/companion/src/firmwares/multiprotocols.cpp index 737bd36ed..c8c18e6e5 100644 --- a/companion/src/firmwares/multiprotocols.cpp +++ b/companion/src/firmwares/multiprotocols.cpp @@ -26,8 +26,8 @@ #define STR_MULTI_SUBTYPE QT_TRANSLATE_NOOP("Multiprotocols", "Subtype") #define STR_MULTI_VIDFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Video TX frequency") #define STR_MULTI_RFTUNE QT_TRANSLATE_NOOP("Multiprotocols", "CC2500 frequency fine tune") +#define STR_MULTI_RFPOWER QT_TRANSLATE_NOOP("Multiprotocols", "RF power") #define STR_MULTI_TELEMETRY QT_TRANSLATE_NOOP("Multiprotocols", "Telemetry") -#define STR_MULTI_RFPOWER QT_TRANSLATE_NOOP("Multiprotocols", "Radio output power") #define STR_MULTI_SERVOFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Servo output frequency") #define STR_MULTI_OPTION QT_TRANSLATE_NOOP("Multiprotocols", "Option value") #define STR_MULTI_FIXEDID QT_TRANSLATE_NOOP("Multiprotocols", "Fixed ID value") @@ -41,8 +41,8 @@ static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V91 static const QStringList STR_SUBTYPE_HUBSAN {"H107", "H301", "H501"}; static const QStringList STR_SUBTYPE_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch", "D8 Cloned", "D16 Cloned"}; static const QStringList STR_SUBTYPE_HISKY {"Standard", "HK310"}; -static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506"}; -static const QStringList STR_SUBTYPE_DSM {"DSM2 22ms", "DSM2 11ms", "DSMX 22ms", "DSMX 11ms"}; +static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506", "MR101"}; +static const QStringList STR_SUBTYPE_DSM {"DSM2 1F", "DSM2 2F", "DSMX 1F", "DSMX 2F"}; static const QStringList STR_SUBTYPE_DEVO {"8 Channel", "10 Channel", "12 Channel", "6 Channel", "7 Channel"}; static const QStringList STR_SUBTYPE_YD717 {"Standard", "Skywalker", "Syma X4", "XINXUN", "NIHUI"}; static const QStringList STR_SUBTYPE_KN {"WLtoys", "FeiLun"}; @@ -71,6 +71,7 @@ static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"}; static const QStringList STR_SUBTYPE_E01X {"E012", "E015", "E016H"}; static const QStringList STR_SUBTYPE_V911S {"Standard", "E119"}; static const QStringList STR_SUBTYPE_GD00X {"GD V1", "GD V2"}; +static const QStringList STR_SUBTYPE_V761 {"3 Channel", "4 Channel"}; static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"}; static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"}; static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"}; @@ -80,7 +81,7 @@ static const QStringList STR_SUBTYPE_HOTT {"Sync", "No_Sync"}; static const QStringList STR_SUBTYPE_FX816 {"P38"}; static const QStringList STR_SUBTYPE_PELIKAN {"Pro", "Lite"}; static const QStringList STR_SUBTYPE_XK {"X450", "X420"}; -static const QStringList STR_SUBTYPE_XN297DUMP {"250K", "1M", "2M", "AUTO"}; +static const QStringList STR_SUBTYPE_XN297DUMP {"250K", "1M", "2M", "AUTO", "NRF"}; static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "D16 Cloned"}; static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel"}; static const QStringList STR_SUBTYPE_PROPEL {"74-Z"}; @@ -97,7 +98,7 @@ const Multiprotocols multiProtocols { {MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ}, {MODULE_SUBTYPE_MULTI_FRSKY, 7, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr}, - {MODULE_SUBTYPE_MULTI_V2X2, 1, false, STR_SUBTYPE_V2X2, nullptr}, + {MODULE_SUBTYPE_MULTI_V2X2, 2, false, STR_SUBTYPE_V2X2, nullptr}, {MODULE_SUBTYPE_MULTI_DSM2, 3, false, STR_SUBTYPE_DSM, nullptr}, {MODULE_SUBTYPE_MULTI_DEVO, 4, false, STR_SUBTYPE_DEVO, STR_MULTI_FIXEDID}, {MODULE_SUBTYPE_MULTI_YD717, 4, false, STR_SUBTYPE_YD717, nullptr}, @@ -130,6 +131,7 @@ const Multiprotocols multiProtocols { {MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION}, {MODULE_SUBTYPE_MULTI_V911S, 1, false, STR_SUBTYPE_V911S, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, STR_MULTI_RFTUNE}, + {MODULE_SUBTYPE_MULTI_V761, 1, false, STR_SUBTYPE_V761, nullptr}, {MODULE_SUBTYPE_MULTI_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr}, @@ -140,7 +142,7 @@ const Multiprotocols multiProtocols { {MODULE_SUBTYPE_MULTI_FX816, 0, false, STR_SUBTYPE_FX816, nullptr}, {MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, STR_SUBTYPE_PELIKAN, nullptr}, {MODULE_SUBTYPE_MULTI_XK, 1, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE}, - {MODULE_SUBTYPE_MULTI_XN297DUMP, 3, false, STR_SUBTYPE_XN297DUMP, nullptr}, + {MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, STR_SUBTYPE_XN297DUMP, nullptr}, {MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr}, {MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr}, diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 17c5b03a5..fcf0fc732 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -128,6 +128,14 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version) return 16; } +inline int MAX_MOUSE_ANALOG_SOURCES(Board::Type board, int version) +{ + if (IS_FAMILY_HORUS_OR_T16(board)) + return 2; + else + return 0; +} + #define MAX_ROTARY_ENCODERS(board) 0 #define MAX_FLIGHT_MODES(board, version) 9 #define MAX_TIMERS(board, version) 3 @@ -300,7 +308,7 @@ class SourcesConversionTable: public ConversionTable { } } - for (int i=0; i= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version)) offset += 2; @@ -721,13 +729,7 @@ class FlightModeField: public TransformedField { trim = 501 + phase.trimRef[i] - (phase.trimRef[i] > index ? 1 : 0); else trim = std::max(-500, std::min(500, phase.trim[i])); - if (board == BOARD_9X_M64 || (board == BOARD_9X_M128 && version >= 215)) { - trimBase[i] = trim >> 2; - trimExt[i] = (trim & 0x03); - } - else { - trimBase[i] = trim; - } + trimBase[i] = trim; } } } @@ -751,11 +753,7 @@ class FlightModeField: public TransformedField { phase.trim[i] = 0; } else { - int trim; - if (board == BOARD_9X_M64 || (board == BOARD_9X_M128 && version >= 215)) - trim = ((trimBase[i]) << 2) + (trimExt[i] & 0x03); - else - trim = trimBase[i]; + int trim = trimBase[i]; if (trim > 500) { phase.trimRef[i] = trim - 501; if (phase.trimRef[i] >= index) @@ -2113,6 +2111,40 @@ class ModuleUnionField: public UnionField { unsigned int version; }; + class Afhds3Field: public UnionField::TransformedMember { + public: + Afhds3Field(DataField * parent, ModuleData& module): + UnionField::TransformedMember(parent, internalField), + internalField(this, "AFHDS3") + { + ModuleData::Afhds3& afhds3 = module.afhds3; + internalField.Append(new UnsignedField<3>(this, minBindPower)); + internalField.Append(new UnsignedField<3>(this, afhds3.rfPower)); + internalField.Append(new UnsignedField<1>(this, emissionFCC)); + internalField.Append(new BoolField<1>(this, operationModeUnicast)); + internalField.Append(new BoolField<1>(this, operationModeUnicast)); + internalField.Append(new UnsignedField<16>(this, defaultFailSafeTimout)); + internalField.Append(new UnsignedField<16>(this, afhds3.rxFreq)); + } + + bool select(const unsigned int& attr) const override { + return attr == PULSES_AFHDS3; + } + + void beforeExport() override {} + + void afterImport() override {} + + private: + StructField internalField; + + unsigned int minBindPower = 0; + unsigned int emissionFCC = 0; + unsigned int defaultFailSafeTimout = 1000; + bool operationModeUnicast = true; + }; + + class AccessField: public UnionField::TransformedMember { public: AccessField(DataField * parent, ModuleData& module): @@ -2173,8 +2205,10 @@ class ModuleUnionField: public UnionField { ModuleUnionField(DataField * parent, ModuleData & module, Board::Type board, unsigned int version): UnionField(parent, module.protocol) { - if (version >= 219) + if (version >= 219) { Append(new AccessField(parent, module)); + Append(new Afhds3Field(parent, module)); + } Append(new PxxField(parent, module, version)); Append(new MultiField(parent, module)); Append(new PPMField(parent, module.ppm)); @@ -2387,7 +2421,8 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode)); } else { - internalField.Append(new SpareBitsField<6>(this)); + internalField.Append(new SpareBitsField<3>(this)); + internalField.Append(new UnsignedField<3>(this, modelData.thrTrimSwitch)); internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode)); } @@ -2543,7 +2578,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type generalData(generalData), board(board), version(version), - inputsCount(CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version) + MAX_SLIDERS_STORAGE(board, version) + Boards::getCapability(board, Board::MouseAnalogs)) + inputsCount(CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version) + MAX_SLIDERS_STORAGE(board, version) + MAX_MOUSE_ANALOG_SOURCES(board, version)) { qCDebug(eepromImport) << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board).arg(version).arg(variant); @@ -2581,7 +2616,13 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type else internalField.Append(new SpareBitsField<2>(this)); internalField.Append(new BoolField<1>(this, generalData.rtcCheckDisable)); - internalField.Append(new SpareBitsField<2>(this)); + if (IS_JUMPER_T18(board)) { + internalField.Append(new BoolField<1>(this, generalData.keysBacklight)); + internalField.Append(new SpareBitsField<1>(this)); + } + else { + internalField.Append(new SpareBitsField<2>(this)); + } for (int i=0; i<4; i++) { internalField.Append(new SignedField<16>(this, generalData.trainer.calib[i])); diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h index ac1cf09dc..bb55b5687 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.h +++ b/companion/src/firmwares/opentx/opentxeeprom.h @@ -37,9 +37,6 @@ #define TARANIS_X9LITES_VARIANT 0x0801 #define JUMPER_T12_VARIANT 0x4001 -#define SIMU_STOCK_VARIANTS (GVARS_VARIANT|FRSKY_VARIANT) -#define SIMU_M128_VARIANTS (M128_VARIANT|SIMU_STOCK_VARIANTS) - class OpenTxGeneralData: public TransformedField { public: OpenTxGeneralData(GeneralSettings & generalData, Board::Type board, unsigned int version, unsigned int variant=0); @@ -99,7 +96,7 @@ class ProtocolsConversionTable: public ConversionTable addConversion(PULSES_ACCESS_R9M, val++); addConversion(PULSES_PXX_R9M_LITE, val++); addConversion(PULSES_ACCESS_R9M_LITE, val++); - addConversion(PULSES_PXX_R9M_LITE_PRO, val++); + addConversion(PULSES_GHOST, val++); addConversion(PULSES_ACCESS_R9M_LITE_PRO, val++); addConversion(PULSES_SBUS, val++); @@ -107,6 +104,10 @@ class ProtocolsConversionTable: public ConversionTable addConversion(PULSES_XJT_LITE_X16, val); addConversion(PULSES_XJT_LITE_D8, val); addConversion(PULSES_XJT_LITE_LR12, val++); + + if (version >= 219) { + addConversion(PULSES_AFHDS3, val++); + } } }; diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 2fed78ab4..1d00c99ad 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -58,18 +58,12 @@ OpenTxEepromInterface::~OpenTxEepromInterface() const char * OpenTxEepromInterface::getName() { switch (board) { - case BOARD_9X_M64: - return "OpenTX for 9X board"; - case BOARD_9X_M128: - return "OpenTX for M128 / 9X board"; - case BOARD_MEGA2560: - return "OpenTX for MEGA2560 board"; - case BOARD_GRUVIN9X: - return "OpenTX for Gruvin9x board / 9X"; case BOARD_JUMPER_T12: return "OpenTX for Jumper T12"; case BOARD_JUMPER_T16: return "OpenTX for Jumper T16"; + case BOARD_JUMPER_T18: + return "OpenTX for Jumper T18"; case BOARD_RADIOMASTER_TX16S: return "OpenTX for Radiomaster TX16S"; case BOARD_TARANIS_X9D: @@ -280,16 +274,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t * uint8_t OpenTxEepromInterface::getLastDataVersion(Board::Type board) { - switch (board) { - case BOARD_9X_M64: - return 216; - case BOARD_GRUVIN9X: - case BOARD_MEGA2560: - case BOARD_9X_M128: - return 217; - default: - return 219; - } + return 219; } void OpenTxEepromInterface::showErrors(const QString & title, const QStringList & errors) @@ -325,10 +310,7 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u efile->EeFsCreate(eeprom, size, board, version); - if (board == BOARD_9X_M128) { - variant |= M128_VARIANT; - } - else if (IS_TARANIS_X9E(board)) { + if (IS_TARANIS_X9E(board)) { variant |= TARANIS_X9E_VARIANT; } else if (IS_TARANIS_X9LITES(board)) { @@ -445,43 +427,26 @@ int OpenTxFirmware::getCapability(::Capability capability) case Models: if (IS_FAMILY_HORUS_OR_T16(board)) return 0; - else if (IS_ARM(board)) + else return 60; - else if (board == BOARD_9X_M128) - return 30; - else if (IS_2560(board)) - return 30; - else - return 16; case Imperial: - if (IS_ARM(board)) - return 0; - else - return id.contains("imperial") ? 1 : 0; + return 0; case ModelImage: return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_FAMILY_HORUS_OR_T16(board)); case HasBeeper: - return (!IS_ARM(board)); + return false; case HasPxxCountry: return 1; case HasGeneralUnits: - if (IS_ARM(board)) - return 1; - else - return 0; + return true; case HasNegAndSwitches: - return IS_ARM(board); + return true; case PPMExtCtrl: return 1; case PPMFrameLength: return 40; case FlightModes: - if (IS_ARM(board)) - return 9; - else if (IS_2560(board)) - return 6; - else - return 5; + return 9; case FlightModesHaveFades: return 1; case Heli: @@ -493,7 +458,7 @@ int OpenTxFirmware::getCapability(::Capability capability) if (IS_HORUS_OR_TARANIS(board)) return id.contains("nogvars") ? 0 : 9; else if (id.contains("gvars")) - return IS_ARM(board) ? 9 : 5; + return 9; else return 0; case ModelName: @@ -501,66 +466,48 @@ int OpenTxFirmware::getCapability(::Capability capability) case FlightModesName: return (IS_HORUS_OR_TARANIS(board) ? 10 : 6); case GvarsName: - return (IS_9X(board) ? 0 : 3); + return 3; case GvarsInCS: case HasFAIMode: return 1; case GvarsAreNamed: case GvarsFlightModes: - return ((IS_ARM(board) || IS_2560(board)) ? 1 : 0); + return 1; case Mixes: - return (IS_ARM(board) ? 64 : 32); + return 64; case OffsetWeight: - return (IS_ARM(board) ? 500 : 245); + return 500; case Timers: - return (IS_ARM(board) ? 3 : 2); + return 3; case TimersName: if (HAS_LARGE_LCD(board)) return 8; - else if (IS_ARM(board)) + else return 3; - else - return 0; case PermTimers: - return (IS_2560(board) || IS_ARM(board)); + return true; case CustomFunctions: - if (IS_ARM(board)) - return 64; - else if (IS_2560(board) || board == BOARD_9X_M128) - return 24; - else - return 16; + return 64; case SafetyChannelCustomFunction: return id.contains("nooverridech") ? 0 : 1; case LogicalSwitches: - if (IS_ARM(board)) - return 64; - else - return 12; + return 64; case CustomAndSwitches: - if (IS_ARM(board)) - return getCapability(LogicalSwitches); - else - return 15/*4bits*/- 9/*sw positions*/; + return getCapability(LogicalSwitches); case LogicalSwitchesExt: - return (IS_ARM(board) ? true : false); + return true; case RotaryEncoders: - if (board == BOARD_GRUVIN9X) - return 2; - else if (IS_SKY9X(board)) - return 1; - else return 0; case Outputs: - return (IS_ARM(board) ? 32 : 16); + return 32; case NumCurvePoints: - return (IS_ARM(board) ? 512 : 104); + return 512; case VoicesAsNumbers: - return (IS_ARM(board) ? 0 : 1); + return 0; case VoicesMaxLength: - return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : 0); + return (IS_TARANIS_X9(board) ? 8 : 6); case MultiLangVoice: - return (IS_ARM(board) ? 1 : 0); + return 1; case SoundPitch: return 1; case Haptic: @@ -571,7 +518,7 @@ int OpenTxFirmware::getCapability(::Capability capability) else return 0; case MaxVolume: - return (IS_ARM(board) ? 23 : 7); + return 23; case MaxContrast: if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board)) return 30; @@ -583,7 +530,7 @@ int OpenTxFirmware::getCapability(::Capability capability) else return 10; case HasSoundMixer: - return (IS_ARM(board) ? 1 : 0); + return 1; case ExtraInputs: return 1; case TrimsRange: @@ -593,29 +540,26 @@ int OpenTxFirmware::getCapability(::Capability capability) case Simulation: return 1; case NumCurves: - return (HAS_LARGE_LCD(board) ? 32 : (IS_ARM(board) ? 16 : 8)); + return 32; case HasMixerNames: - return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : false); + return (IS_TARANIS_X9(board) ? 8 : 6); case HasExpoNames: - return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : false); + return (IS_TARANIS_X9(board) ? 8 : 6); case HasNoExpo: return (IS_HORUS_OR_TARANIS(board) ? false : true); case ChannelsName: - return (IS_ARM(board) ? (HAS_LARGE_LCD(board) ? 6 : 4) : 0); + return (HAS_LARGE_LCD(board) ? 6 : 4); case HasCvNames: - return (IS_ARM(board) ? 1 : 0); + return 1; case Telemetry: - if (IS_2560(board) || IS_ARM(board) || id.contains("frsky") || id.contains("telemetrez")) - return TM_HASTELEMETRY | TM_HASOFFSET | TM_HASWSHH; - else - return 0; + return 1; case TelemetryBars: return 1; case TelemetryCustomScreens: if (IS_FAMILY_HORUS_OR_T16(board)) return 0; else - return IS_ARM(board) ? 4 : 2; + return 4; case TelemetryCustomScreensBars: return (getCapability(TelemetryCustomScreens) ? 4 : 0); case TelemetryCustomScreensLines: @@ -627,7 +571,7 @@ int OpenTxFirmware::getCapability(::Capability capability) case TelemetryUnits: return 0; case TelemetryMaxMultiplier: - return (IS_ARM(board) ? 32 : 8); + return 32; case PPMCenter: return (IS_HORUS_OR_TARANIS(board) ? 500 : (id.contains("ppmca") ? 125 : 0)); case PPMUnitMicroseconds: @@ -639,35 +583,35 @@ int OpenTxFirmware::getCapability(::Capability capability) case HasVario: return 1; case HasVarioSink: - return ((IS_2560(board) || IS_ARM(board)) ? true : false); + return true; case HasFailsafe: - return (IS_ARM(board) ? 32 : 0); + return 32; case NumModules: - return (IS_ARM(board) ? 2 : 1); + return 2; case NumFirstUsableModule: - return (IS_JUMPER_T12(board) ? 1 : 0); + return (IS_JUMPER_T12(board) && !id.contains("internalmulti") ? 1 : 0); case HasModuleR9MFlex: return id.contains("flexr9m"); case HasModuleR9MMini: return IS_TARANIS_XLITE(board) && !id.contains("stdr9m"); case HasPPMStart: - return (IS_ARM(board) ? true : false); + return true; case HastxCurrentCalibration: return (IS_SKY9X(board) ? true : false); case HasVolume: - return (IS_ARM(board) ? true : false); + return true; case HasBrightness: - return (IS_ARM(board) ? true : false); + return true; case PerModelTimers: return 1; case SlowScale: - return (IS_ARM(board) ? 10 : 2); + return 10; case SlowRange: - return (IS_ARM(board) ? 250 : 15); + return 250; case CSFunc: return 18; case HasSDLogs: - return ((IS_2560(board) || IS_ARM(board)) ? true : false); + return true; case LcdWidth: if (IS_FAMILY_HORUS_OR_T16(board)) return 480; @@ -694,19 +638,19 @@ int OpenTxFirmware::getCapability(::Capability capability) case GetThrSwitch: return (IS_HORUS_OR_TARANIS(board) ? SWITCH_SF1 : SWITCH_THR); case HasDisplayText: - return IS_ARM(board) ? 1 : 0; + return 1; case HasTopLcd: return IS_TARANIS_X9E(board) ? 1 : 0; case GlobalFunctions: - return IS_ARM(board) ? 64 : 0; + return 64; case VirtualInputs: - return IS_ARM(board) ? 32 : 0; + return 32; case InputsLength: return HAS_LARGE_LCD(board) ? 4 : 3; case TrainerInputs: - return IS_ARM(board) ? 16 : 8; + return 16; case RtcTime: - return IS_ARM(board) || IS_2560(board) ? 1 : 0; + return 1; case LuaScripts: return IS_HORUS_OR_TARANIS(board) && id.contains("lua") ? 7 : 0; case LuaInputsPerScript: @@ -715,17 +659,13 @@ int OpenTxFirmware::getCapability(::Capability capability) return IS_HORUS_OR_TARANIS(board) ? 6 : 0; case LimitsPer1000: case EnhancedCurves: - return IS_ARM(board); + return 1; case HasFasOffset: - return (IS_STOCK(board) ? false : true); + return true; case HasMahPersistent: - return (IS_ARM(board) ? true : false); + return true; case SimulatorVariant: - if (board == BOARD_9X_M64) - return SIMU_STOCK_VARIANTS; - else if (board == BOARD_9X_M128) - return SIMU_M128_VARIANTS; - else if (IS_TARANIS_X9E(board)) + if (IS_TARANIS_X9E(board)) return TARANIS_X9E_VARIANT; else if (IS_TARANIS_X9LITES(board)) return TARANIS_X9LITES_VARIANT; @@ -744,7 +684,7 @@ int OpenTxFirmware::getCapability(::Capability capability) case MavlinkTelemetry: return id.contains("mavlink") ? 1 : 0; case SportTelemetry: - return IS_ARM(board) ? 1 : 0; + return 1; case HasInputDiff: case HasMixerExpo: return (IS_HORUS_OR_TARANIS(board) ? true : false); @@ -777,10 +717,8 @@ QTime OpenTxFirmware::getMaxTimerStart() { if (IS_HORUS_OR_TARANIS(board)) return QTime(23, 59, 59); - else if (IS_ARM(board)) - return QTime(8, 59, 59); else - return QTime(0, 59, 59); + return QTime(8, 59, 59); } bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) @@ -793,16 +731,14 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) return true; case PULSES_PXX_XJT_X16: case PULSES_PXX_XJT_LR12: - return !IS_ACCESS_RADIO(board, id) && !IS_FAMILY_T16(board); + return !IS_ACCESS_RADIO(board, id) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board); case PULSES_PXX_XJT_D8: - return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board); - case PULSES_PPM: - return id.contains("internalppm"); + return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board); case PULSES_ACCESS_ISRM: case PULSES_ACCST_ISRM_D16: return IS_ACCESS_RADIO(board, id); case PULSES_MULTIMODULE: - return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board); + return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board); default: return false; } @@ -823,9 +759,11 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) case PULSES_SBUS: case PULSES_MULTIMODULE: case PULSES_CROSSFIRE: + case PULSES_AFHDS3: + case PULSES_GHOST: return true; case PULSES_ACCESS_R9M: - return IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess")); + return IS_ACCESS_RADIO(board, id); case PULSES_PXX_R9M_LITE: case PULSES_ACCESS_R9M_LITE: case PULSES_ACCESS_R9M_LITE_PRO: @@ -946,14 +884,9 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version) // M128 revert because too much RAM used! case 216: // A lot of things (first github release) - if (IS_2560(board) || IS_M128(board)) { - return OLD_VERSION; - } case 217: // 3 logical switches removed on M128 / gruvin9x boards - if (IS_ARM(board)) { return OLD_VERSION; - } case 218: // ACCESS // switches add for X7/X10/X12S @@ -973,21 +906,7 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version) bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int variant) { bool variantError = false; - if (board == BOARD_9X_M128 && !(variant & M128_VARIANT)) { - if (version == 212) { - uint8_t tmp[1000]; - for (int i = 1; i < 31; i++) { - efile->openRd(i); - int sz = efile->readRlc2(tmp, sizeof(tmp)); - if (sz == 849) { - qWarning() << " warning: M128 variant not set (but model size seems ok)"; - return true; - } - } - } - variantError = true; - } - else if (IS_TARANIS_X9E(board)) { + if (IS_TARANIS_X9E(board)) { if (variant != TARANIS_X9E_VARIANT) { variantError = true; } @@ -1079,9 +998,6 @@ unsigned long OpenTxEepromInterface::loadBackup(RadioData &radioData, const uint case 0x32: backupBoard = BOARD_SKY9X; break; - case 0x31: - backupBoard = BOARD_GRUVIN9X; - break; default: dbg << " unknown board"; errors.set(UNKNOWN_BOARD); @@ -1184,19 +1100,25 @@ void addOpenTxCommonOptions(OpenTxFirmware * firmware) enum RfOptions { NONE = 0, EU = 1 << 0, - FLEX = 1 << 1 + FLEX = 1 << 1, + AFHDS3 = 1 << 2 }; void addOpenTxRfOptions(OpenTxFirmware * firmware, uint8_t options) { static const Firmware::Option opt_eu("eu", Firmware::tr("Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015")); static const Firmware::Option opt_fl("flexr9m", Firmware::tr("Enable non certified firmwares")); - if (options == EU + FLEX) + static const Firmware::Option opt_afhds3("afhds3", Firmware::tr("Enable AFHDS3 support")); + + + if ((options & (EU + FLEX)) == EU + FLEX) firmware->addOptionsGroup({opt_eu, opt_fl}); - else if (options == EU) + else if ((options & EU) != 0) firmware->addOption(opt_eu); - else if (options == FLEX) + else if ((options & FLEX) != 0) firmware->addOption(opt_fl); + if ((options & AFHDS3) != 0) + firmware->addOption(opt_afhds3); } void addOpenTxFontOptions(OpenTxFirmware * firmware) @@ -1245,7 +1167,7 @@ void registerOpenTxFirmwares() firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)")); addOpenTxTaranisOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, EU + FLEX); + addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3); /* FrSky Taranis X9D+ 2019 board */ firmware = new OpenTxFirmware("opentx-x9d+2019", Firmware::tr("FrSky Taranis X9D+ 2019"), BOARD_TARANIS_X9DP_2019); @@ -1259,7 +1181,7 @@ void registerOpenTxFirmwares() firmware->addOption("haptic", Firmware::tr("Haptic module installed")); addOpenTxTaranisOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, EU + FLEX); + addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3); /* FrSky Taranis X9E board */ firmware = new OpenTxFirmware("opentx-x9e", Firmware::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E); @@ -1267,19 +1189,19 @@ void registerOpenTxFirmwares() firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)")); addOpenTxTaranisOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, EU + FLEX); + addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3); /* FrSky X9-Lite board */ firmware = new OpenTxFirmware("opentx-x9lite", Firmware::tr("FrSky Taranis X9-Lite"), BOARD_TARANIS_X9LITE); addOpenTxTaranisOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, FLEX); + addOpenTxRfOptions(firmware, FLEX + AFHDS3); /* FrSky X9-LiteS board */ firmware = new OpenTxFirmware("opentx-x9lites", Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES); addOpenTxTaranisOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, FLEX); + addOpenTxRfOptions(firmware, FLEX + AFHDS3); /* FrSky X7 board */ firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7); @@ -1297,7 +1219,7 @@ void registerOpenTxFirmwares() firmware = new OpenTxFirmware("opentx-xlites", Firmware::tr("FrSky Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES); addOpenTxTaranisOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, FLEX); + addOpenTxRfOptions(firmware, FLEX + AFHDS3); /* FrSky X-Lite board */ firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE); @@ -1336,7 +1258,7 @@ void registerOpenTxFirmwares() firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module")); addOpenTxFontOptions(firmware); registerOpenTxFirmware(firmware); - addOpenTxRfOptions(firmware, FLEX); + addOpenTxRfOptions(firmware, FLEX + AFHDS3); /* Jumper T16 board */ firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16); @@ -1347,7 +1269,7 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); /* Radiomaster TX16S board */ - firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16s / TX16s Hall / TX16s Masterfire"), BOARD_RADIOMASTER_TX16S); + firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S); addOpenTxFrskyOptions(firmware); addOpenTxRfOptions(firmware, FLEX); static const Firmware::Option opt_bt("bluetooth", Firmware::tr("Support for bluetooth module")); @@ -1355,6 +1277,13 @@ void registerOpenTxFirmwares() firmware->addOptionsGroup({opt_bt, opt_internal_gps}); registerOpenTxFirmware(firmware); + /* Jumper T18 board */ + firmware = new OpenTxFirmware("opentx-t18", Firmware::tr("Jumper T18"), BOARD_JUMPER_T18); + addOpenTxFrskyOptions(firmware); + firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module")); + registerOpenTxFirmware(firmware); + addOpenTxRfOptions(firmware, FLEX); + /* 9XR-Pro */ firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO); addOpenTxArm9xOptions(firmware, false); @@ -1372,14 +1301,6 @@ void registerOpenTxFirmwares() addOpenTxArm9xOptions(firmware); registerOpenTxFirmware(firmware); - // These are kept only for import purposes, marked as deprecated to hide from UI. - registerOpenTxFirmware(new OpenTxFirmware("opentx-9xr", Firmware::tr("Turnigy 9XR"), BOARD_9X_M64), true); - registerOpenTxFirmware(new OpenTxFirmware("opentx-9xr128", Firmware::tr("Turnigy 9XR with m128 chip"), BOARD_9X_M128), true); - registerOpenTxFirmware(new OpenTxFirmware("opentx-9x", Firmware::tr("9X with stock board"), BOARD_9X_M64), true); - registerOpenTxFirmware(new OpenTxFirmware("opentx-9x128", Firmware::tr("9X with stock board and m128 chip"), BOARD_9X_M128), true); - registerOpenTxFirmware(new OpenTxFirmware("opentx-gruvin9x", Firmware::tr("9X with Gruvin9x board"), BOARD_GRUVIN9X), true); - registerOpenTxFirmware(new OpenTxFirmware("opentx-mega2560", Firmware::tr("DIY MEGA2560 radio"), BOARD_MEGA2560), true); - Firmware::setDefaultVariant(Firmware::getFirmwareForId("opentx-x9d+")); Firmware::setCurrentVariant(Firmware::getDefaultVariant()); } diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index 401eb9781..92377fe0a 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -32,10 +32,7 @@ float RawSourceRange::getValue(int value) { - if (IS_ARM(getCurrentBoard())) - return float(value) * step; - else - return min + float(value) * step; + return float(value) * step; } @@ -48,11 +45,10 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting RawSourceRange result; Firmware * firmware = Firmware::getCurrentVariant(); - Board::Type board = firmware->getBoard(); switch (type) { case SOURCE_TYPE_TELEMETRY: - if (IS_ARM(board)) { + { div_t qr = div(index, 3); const SensorData & sensor = model->sensorData[qr.quot]; if (sensor.prec == 2) @@ -65,192 +61,8 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting result.max = +30000 * result.step; result.decimals = sensor.prec; result.unit = sensor.unitString(); + break; } - else { - result.offset = -DBL_MAX; - - switch (index) { - case TELEMETRY_SOURCE_TX_BATT: - result.step = 0.1; - result.decimals = 1; - result.max = 25.5; - result.unit = tr("V"); - break; - case TELEMETRY_SOURCE_TX_TIME: - result.step = 60; - result.max = 24 * 60 * result.step - 60; // 23:59:00 with 1-minute resolution - result.unit = tr("s"); - break; - case TELEMETRY_SOURCE_TIMER1: - case TELEMETRY_SOURCE_TIMER2: - case TELEMETRY_SOURCE_TIMER3: - result.step = 5; - result.max = 255 * result.step; - result.unit = tr("s"); - break; - case TELEMETRY_SOURCE_RSSI_TX: - case TELEMETRY_SOURCE_RSSI_RX: - result.max = 100; - result.offset = 128; - break; - case TELEMETRY_SOURCE_A1_MIN: - case TELEMETRY_SOURCE_A2_MIN: - case TELEMETRY_SOURCE_A3_MIN: - case TELEMETRY_SOURCE_A4_MIN: - if (model) result = model->frsky.channels[index-TELEMETRY_SOURCE_A1_MIN].getRange(); - break; - case TELEMETRY_SOURCE_A1: - case TELEMETRY_SOURCE_A2: - case TELEMETRY_SOURCE_A3: - case TELEMETRY_SOURCE_A4: - if (model) result = model->frsky.channels[index-TELEMETRY_SOURCE_A1].getRange(); - break; - case TELEMETRY_SOURCE_ALT: - case TELEMETRY_SOURCE_ALT_MIN: - case TELEMETRY_SOURCE_ALT_MAX: - case TELEMETRY_SOURCE_GPS_ALT: - result.step = 8; - result.min = -500; - result.max = 1540; - if (firmware->getCapability(Imperial) || settings.imperial) { - result.step = (result.step * 105) / 32; - result.min = (result.min * 105) / 32; - result.max = (result.max * 105) / 32; - result.unit = tr("ft"); - } - else { - result.unit = tr("m"); - } - break; - case TELEMETRY_SOURCE_T1: - case TELEMETRY_SOURCE_T1_MAX: - case TELEMETRY_SOURCE_T2: - case TELEMETRY_SOURCE_T2_MAX: - result.min = -30; - result.max = 225; - result.unit = tr("°C"); - break; - case TELEMETRY_SOURCE_HDG: - result.step = 2; - result.max = 360; - result.offset = 256; - result.unit = tr("°"); - break; - case TELEMETRY_SOURCE_RPM: - case TELEMETRY_SOURCE_RPM_MAX: - result.step = 50; - result.max = 12750; - break; - case TELEMETRY_SOURCE_FUEL: - result.max = 100; - result.unit = tr("%"); - break; - case TELEMETRY_SOURCE_ASPEED: - case TELEMETRY_SOURCE_ASPEED_MAX: - result.decimals = 1; - result.step = 2.0; - result.max = (2*255); - if (firmware->getCapability(Imperial) || settings.imperial) { - result.step *= 1.150779; - result.max *= 1.150779; - result.unit = tr("mph"); - } - else { - result.step *= 1.852; - result.max *= 1.852; - result.unit = tr("km/h"); - } - break; - case TELEMETRY_SOURCE_SPEED: - case TELEMETRY_SOURCE_SPEED_MAX: - result.step = 2; - result.max = (2*255); - if (firmware->getCapability(Imperial) || settings.imperial) { - result.step *= 1.150779; - result.max *= 1.150779; - result.unit = tr("mph"); - } - else { - result.step *= 1.852; - result.max *= 1.852; - result.unit = tr("km/h"); - } - break; - case TELEMETRY_SOURCE_VERTICAL_SPEED: - result.step = 0.1; - result.min = -12.5; - result.max = 13.0; - result.decimals = 1; - result.unit = tr("m/s"); - break; - case TELEMETRY_SOURCE_DTE: - result.max = 30000; - break; - case TELEMETRY_SOURCE_DIST: - case TELEMETRY_SOURCE_DIST_MAX: - result.step = 8; - result.max = 2040; - result.unit = tr("m"); - break; - case TELEMETRY_SOURCE_CELL: - case TELEMETRY_SOURCE_CELL_MIN: - result.step = 0.02; - result.max = 5.1; - result.decimals = 2; - result.unit = tr("V"); - break; - case TELEMETRY_SOURCE_CELLS_SUM: - case TELEMETRY_SOURCE_CELLS_MIN: - case TELEMETRY_SOURCE_VFAS: - case TELEMETRY_SOURCE_VFAS_MIN: - result.step = 0.1; - result.max = 25.5; - result.decimals = 1; - result.unit = tr("V"); - break; - case TELEMETRY_SOURCE_CURRENT: - case TELEMETRY_SOURCE_CURRENT_MAX: - result.step = 0.5; - result.max = 127.5; - result.decimals = 1; - result.unit = tr("A"); - break; - case TELEMETRY_SOURCE_CONSUMPTION: - result.step = 100; - result.max = 25500; - result.unit = tr("mAh"); - break; - case TELEMETRY_SOURCE_POWER: - case TELEMETRY_SOURCE_POWER_MAX: - result.step = 5; - result.max = 1275; - result.unit = tr("W"); - break; - case TELEMETRY_SOURCE_ACCX: - case TELEMETRY_SOURCE_ACCY: - case TELEMETRY_SOURCE_ACCZ: - result.step = 0.01; - result.decimals = 2; - result.max = 2.55; - result.min = 0; - result.unit = tr("g"); - break; - default: - result.max = 125; - break; - } - - if (result.offset == -DBL_MAX) { - result.offset = result.max - (127*result.step); - } - - if (flags & (RANGE_DELTA_FUNCTION | RANGE_ABS_FUNCTION)) { - result.offset = 0; - result.min = result.step * -127; - result.max = result.step * 127; - } - } - break; case SOURCE_TYPE_LUA_OUTPUT: result.max = 30000; @@ -328,21 +140,6 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"), }; - static const QString telemetry[] = { - tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"), - tr("RAS"), tr("RSSI Tx"), tr("RSSI Rx"), - tr("A1"), tr("A2"), tr("A3"), tr("A4"), - tr("Alt"), tr("Rpm"), tr("Fuel"), tr("T1"), tr("T2"), - tr("Speed"), tr("Dist"), tr("GPS Alt"), - tr("Cell"), tr("Cells"), tr("Vfas"), tr("Curr"), tr("Cnsp"), tr("Powr"), - tr("AccX"), tr("AccY"), tr("AccZ"), - tr("Hdg "), tr("VSpd"), tr("AirSpeed"), tr("dTE"), - tr("A1-"), tr("A2-"), tr("A3-"), tr("A4-"), - tr("Alt-"), tr("Alt+"), tr("Rpm+"), tr("T1+"), tr("T2+"), tr("Speed+"), tr("Dist+"), tr("AirSpeed+"), - tr("Cell-"), tr("Cells-"), tr("Vfas-"), tr("Curr+"), tr("Powr+"), - tr("ACC"), tr("GPS Time"), - }; - static const QString rotary[] = { tr("REa"), tr("REb") }; if (index<0) { @@ -411,10 +208,22 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return LimitData().nameToString(index); case SOURCE_TYPE_SPECIAL: - return CHECK_IN_ARRAY(special, index); + result = CHECK_IN_ARRAY(special, index); + // TODO refactor timers into own source type + if (result.startsWith("Timer")) { + bool ok; + int n = result.right(1).toInt(&ok); + if (ok) { + if (model) + result = model->timers[n - 1].nameToString(n - 1); + else + result = TimerData().nameToString(n - 1); + } + } + return result; case SOURCE_TYPE_TELEMETRY: - if (IS_ARM(board)) { + { div_t qr = div(index, 3); if (model) result = model->sensorData[qr.quot].nameToString(qr.quot); @@ -424,9 +233,6 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con result += (qr.rem == 1 ? "-" : "+"); return result; } - else { - return CHECK_IN_ARRAY(telemetry, index); - } case SOURCE_TYPE_GVAR: if (model) @@ -486,13 +292,7 @@ bool RawSource::isSlider(int * sliderIndex, Board::Type board) const bool RawSource::isTimeBased(Board::Type board) const { - if (board == Board::BOARD_UNKNOWN) - board = getCurrentBoard(); - - if (IS_ARM(board)) - return (type == SOURCE_TYPE_SPECIAL && index > 0); - else - return (type==SOURCE_TYPE_TELEMETRY && (index==TELEMETRY_SOURCE_TX_TIME || index==TELEMETRY_SOURCE_TIMER1 || index==TELEMETRY_SOURCE_TIMER2 || index==TELEMETRY_SOURCE_TIMER3)); + return (type == SOURCE_TYPE_SPECIAL && index > 0); } bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const @@ -516,20 +316,9 @@ bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings return false; if (type == SOURCE_TYPE_TELEMETRY) { - if (IS_ARM(board) && !model->sensorData[div(index, 3).quot].isAvailable()) { + if (!model->sensorData[div(index, 3).quot].isAvailable()) { return false; } - else if (!IS_ARM(board)) { - Firmware * fw = getCurrentFirmware(); - if (type == (int)TELEMETRY_SOURCE_TX_TIME && !fw->getCapability(RtcTime)) - return false; - - if (type == (int)TELEMETRY_SOURCE_RAS && !fw->getCapability(SportTelemetry)) - return false; - - if (type == (int)TELEMETRY_SOURCE_TIMER3 && fw->getCapability(Timers) < 3) - return false; - } } } @@ -555,111 +344,40 @@ RawSource RawSource::convert(RadioDataConversionState & cstate) RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType)); if (type == SOURCE_TYPE_STICK) { - if (cstate.toBoard.getCapability(Board::Sliders)) { - if (index >= cstate.fromBoard.getCapability(Board::Sticks) + cstate.fromBoard.getCapability(Board::Pots)) { - // 1st slider alignment - index += cstate.toBoard.getCapability(Board::Pots) - cstate.fromBoard.getCapability(Board::Pots); - } - - if (isSlider(0, cstate.fromType)) { - // LS and RS sliders are after 2 aux sliders on X12 and X9E - if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) { - if (index >= 7) { - index += 2; // LS/RS to LS/RS - } - } - else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) { - if (index >= 7 && index <= 8) { - index += 2; // aux sliders to spare analogs (which may not exist, this is validated later) - evt = RadioDataConversionState::EVT_CVRT; - } - else if (index >= 9 && index <= 10) { - index -= 2; // LS/RS to LS/RS - } - } - } - } - - if (IS_TARANIS(cstate.toType) && IS_FAMILY_HORUS_OR_T16(cstate.fromType)) { - if (index == 6) - index = 5; // pot S2 to S2 - else if (index == 5) - index = -1; // 6P on Horus doesn't exist on Taranis - } - else if (IS_FAMILY_HORUS_OR_T16(cstate.toType) && IS_TARANIS(cstate.fromType) && index == 5) - { - index = 6; // pot S2 to S2 - } - - } // SOURCE_TYPE_STICK + QStringList fromStickList(getStickList(cstate.fromBoard)); + QStringList toStickList(getStickList(cstate.toBoard)); + index = toStickList.indexOf(fromStickList.at(oldData.id)); + // index set to -1 if no match found + // perform forced mapping + } if (type == SOURCE_TYPE_SWITCH) { - // SWI to SWR don't exist on !X9E board - if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) { - if (index >= 8) { - index = index % 8; - evt = RadioDataConversionState::EVT_CVRT; + QStringList fromSwitchList(getSwitchList(cstate.fromBoard)); + QStringList toSwitchList(getSwitchList(cstate.toBoard)); + index = toSwitchList.indexOf(fromSwitchList.at(oldData.id)); + // index set to -1 if no match found + // perform forced mapping + if (index < 0) { + if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { + // No SE and SG on X7 board + index = toSwitchList.indexOf("SD"); + if (index >= 0) + evt = RadioDataConversionState::EVT_CVRT; + } + else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { + // No SE and SG on T12 board + index = toSwitchList.indexOf("SD"); + if (index >= 0) + evt = RadioDataConversionState::EVT_CVRT; } } - - if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { - // No SE and SG on X7 board - if (index == 4 || index == 6) { - index = 3; // SG and SE to SD - evt = RadioDataConversionState::EVT_CVRT; - } - else if (index == 5) { - index = 4; // SF to SF - } - else if (index == 7) { - index = 5; // SH to SH - } - } - else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { - // No SE and SG on T12 board - if (index == 4 || index == 6) { - index = 3; // SG and SE to SD - evt = RadioDataConversionState::EVT_CVRT; - } - else if (index == 5) { - index = 4; // SF to SF - } - else if (index == 7) { - index = 5; // SH to SH - } - } - // Compensate for SE and SG on X9/Horus board if converting from X7 - else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) { - if (index == 4) { - index = 5; // SF to SF - } - else if (index == 5) { - index = 7; // SH to SH - } - } - else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) { - if (index == 4) { - index = 5; // SF to SF - } - else if (index == 5) { - index = 7; // SH to SH - } - } - else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) { - if (index == 4) { - index = 5; // SF to SF - } - else if (index == 5) { - index = 7; // SH to SH - } - } - } // SOURCE_TYPE_SWITCH + } // final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted) - if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) { + if (index < 0 || !isAvailable(NULL, cstate.toGS(), cstate.toType)) { cstate.setInvalid(oldData); - index = -1; // TODO: better way to flag invalid sources? - type = MAX_SOURCE_TYPE; + // no source is safer than an invalid one + clear(); } else if (evt == RadioDataConversionState::EVT_CVRT) { cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType))); @@ -671,3 +389,24 @@ RawSource RawSource::convert(RadioDataConversionState & cstate) return *this; } + +QStringList RawSource::getStickList(Boards board) const +{ + QStringList ret; + + for (int i = 0; i < board.getCapability(Board::MaxAnalogs); i++) { + ret.append(board.getAnalogInputName(i)); + } + return ret; +} + +QStringList RawSource::getSwitchList(Boards board) const +{ + QStringList ret; + + for (int i = 0; i < board.getCapability(Board::Switches); i++) { + ret.append(board.getSwitchInfo(i).name); + } + return ret; +} + diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h index f59ab70f5..9d0b19450 100644 --- a/companion/src/firmwares/rawsource.h +++ b/companion/src/firmwares/rawsource.h @@ -159,10 +159,6 @@ enum TelemetrySource { TELEMETRY_SOURCE_RESERVE = -1 }; -#define TM_HASTELEMETRY 0x01 -#define TM_HASOFFSET 0x02 -#define TM_HASWSHH 0x04 - enum RawSourceType { SOURCE_TYPE_NONE, SOURCE_TYPE_VIRTUAL_INPUT, @@ -256,6 +252,8 @@ class RawSource { bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const; bool isSet() const { return type != SOURCE_TYPE_NONE || index != 0; } void clear() { type = SOURCE_TYPE_NONE; index = 0; } + QStringList getStickList(Boards board) const; + QStringList getSwitchList(Boards board) const; bool operator == ( const RawSource & other) const { return (this->type == other.type) && (this->index == other.index); diff --git a/companion/src/firmwares/rawswitch.cpp b/companion/src/firmwares/rawswitch.cpp index a689ceea7..8c1685a25 100644 --- a/companion/src/firmwares/rawswitch.cpp +++ b/companion/src/firmwares/rawswitch.cpp @@ -184,77 +184,39 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate) RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE; RadioDataConversionState::LogField oldData(index, toString(cstate.fromType, cstate.fromGS(), cstate.fromModel())); + int newIdx = 0; + if (type == SWITCH_TYPE_SWITCH) { - int srcIdx = div(abs(index)-1, 3).quot; // raw source index - int delta = 0; - - // SWI to SWR don't exist on !X9E board - if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) { - if (srcIdx > 7) { - index %= 24; - evt = RadioDataConversionState::EVT_CVRT; - } - } - - // No SE and SG on X7 board - if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { - if (srcIdx == 4 || srcIdx == 5) { - delta = 3; // SE to SD & SF to SF - if (srcIdx == 4) + div_t swtch = div(abs(index) - 1, 3); // rawsource index + QStringList fromSwitchList(getSwitchList(cstate.fromBoard)); + QStringList toSwitchList(getSwitchList(cstate.toBoard)); + // set to -1 if no match found + newIdx = toSwitchList.indexOf(fromSwitchList.at(swtch.quot)); + // perform forced mapping + if (newIdx < 0) { + if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { + // No SE and SG on X7 board + newIdx = toSwitchList.indexOf("SD"); + if (newIdx >= 0) evt = RadioDataConversionState::EVT_CVRT; } - else if (srcIdx == 6) { - delta = 9; // SG to SD - evt = RadioDataConversionState::EVT_CVRT; - } - else if (srcIdx == 7) { - delta = 6; // SH to SH - } - } - else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { - if (srcIdx == 4 || srcIdx == 5) { - delta = 3; // SE to SD & SF to SF - if (srcIdx == 4) + else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { + // No SE and SG on T12 board + newIdx = toSwitchList.indexOf("SD"); + if (newIdx >= 0) evt = RadioDataConversionState::EVT_CVRT; } - else if (srcIdx == 6) { - delta = 9; // SG to SD - evt = RadioDataConversionState::EVT_CVRT; - } - else if (srcIdx == 7) { - delta = 6; // SH to SH - } - } - // Compensate for SE and SG on X9/Horus board if converting from X7 - else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) { - if (srcIdx == 4) { - delta = -3; // SF to SF - } - else if (srcIdx == 5) { - delta = -6; // SH to SH - } - } - else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) { - if (srcIdx == 4) { - delta = -3; // SF to SF - } - else if (srcIdx == 5) { - delta = -6; // SH to SH - } } - if (index < 0) { - delta = -delta; // invert for !switch - } - - index -= delta; - + if (newIdx >= 0) + index = (newIdx * 3 + 1 + swtch.rem) * (index < 0 ? -1 : 1); } // SWITCH_TYPE_SWITCH // final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted) - if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) { + if (newIdx < 0 || !isAvailable(NULL, cstate.toGS(), cstate.toType)) { cstate.setInvalid(oldData); - type = MAX_SWITCH_TYPE; // TODO: better way to flag invalid switches? + // no switch is safer than an invalid one + clear(); } else if (evt == RadioDataConversionState::EVT_CVRT) { cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel()))); @@ -266,3 +228,13 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate) return *this; } + +QStringList RawSwitch::getSwitchList(Boards board) const +{ + QStringList ret; + + for (int i = 0; i < board.getCapability(Board::Switches); i++) { + ret.append(board.getSwitchInfo(i).name); + } + return ret; +} diff --git a/companion/src/firmwares/rawswitch.h b/companion/src/firmwares/rawswitch.h index d79ac0aa6..7c0707a6a 100644 --- a/companion/src/firmwares/rawswitch.h +++ b/companion/src/firmwares/rawswitch.h @@ -89,6 +89,7 @@ class RawSwitch { bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const; bool isSet() const { return type != SWITCH_TYPE_NONE || index != 0; } void clear() { type = SWITCH_TYPE_NONE; index = 0; } + QStringList getSwitchList(Boards board) const; bool operator== ( const RawSwitch& other) const { return (this->type == other.type) && (this->index == other.index); diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index 0a7e7eada..a9b8d7640 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -84,6 +84,12 @@ QString SensorData::unitString() const return tr("V"); case UNIT_MILLILITERS_PER_MINUTE: return tr("ml/minute"); + case UNIT_HERZ: + return tr("Hertz"); + case UNIT_MS: + return tr("mS"); + case UNIT_US: + return tr("uS"); default: return ""; } @@ -98,7 +104,7 @@ QString SensorData::getOrigin(const ModelData * model) const { if (type != TELEM_TYPE_CUSTOM || !id) return QString(); - + const ModuleData & module = model->moduleData[moduleIdx]; if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) { return QString(module.access.receiverName[rxIdx]); @@ -107,3 +113,8 @@ QString SensorData::getOrigin(const ModelData * model) const return QString(); } } + +bool SensorData::isEmpty() const +{ + return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0); +} diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index 3f995ea3e..a2b993bcc 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -24,6 +24,7 @@ #include constexpr int CPN_MAX_SENSORS = 60; +constexpr int SENSOR_LABEL_LEN = 4; class ModelData; @@ -94,10 +95,10 @@ class SensorData { UNIT_MILLILITERS, UNIT_FLOZ, UNIT_MILLILITERS_PER_MINUTE, - UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE, - UNIT_SPARE1, - UNIT_SPARE2, - UNIT_SPARE3, + UNIT_HERZ, + UNIT_MS, + UNIT_US, + UNIT_MAX = UNIT_US, UNIT_SPARE4, UNIT_SPARE5, UNIT_SPARE6, @@ -133,7 +134,7 @@ class SensorData { unsigned int moduleIdx; unsigned int persistentValue; unsigned int formula; - char label[4+1]; + char label[SENSOR_LABEL_LEN + 1]; unsigned int unit; unsigned int prec; bool autoOffset; @@ -166,6 +167,7 @@ class SensorData { QString nameToString(int index) const; QString getOrigin(const ModelData* model) const; void clear() { memset(this, 0, sizeof(SensorData)); } + bool isEmpty() const; }; #endif // SENSORDATA_H diff --git a/companion/src/firmwares/telem_data.cpp b/companion/src/firmwares/telem_data.cpp index af31f3b38..99743c7e2 100644 --- a/companion/src/firmwares/telem_data.cpp +++ b/companion/src/firmwares/telem_data.cpp @@ -48,9 +48,6 @@ RawSourceRange FrSkyChannelData::getRange() const void FrSkyScreenData::clear() { memset(reinterpret_cast(this), 0, sizeof(FrSkyScreenData)); - if (!IS_ARM(getCurrentBoard())) { - type = TELEMETRY_SCREEN_NUMBERS; - } } void FrSkyData::clear() diff --git a/companion/src/flashfirmwaredialog.cpp b/companion/src/flashfirmwaredialog.cpp index 4650cd4c0..fc45a89ff 100644 --- a/companion/src/flashfirmwaredialog.cpp +++ b/companion/src/flashfirmwaredialog.cpp @@ -275,11 +275,12 @@ void FlashFirmwareDialog::startFlash(const QString &filename) ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png")); // check hardware compatibility if requested + bool checkPassed = true; if (g.checkHardwareCompatibility()) { QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin"); if (!readFirmware(tempFirmware, progressDialog.progress())) { QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio")); - return; + checkPassed = false; } FirmwareInterface previousFirmware(tempFirmware); qunlink(tempFirmware); @@ -291,41 +292,44 @@ void FlashFirmwareDialog::startFlash(const QString &filename) qDebug() << "startFlash: removing temporary file" << filename; qunlink(filename); } - return; + checkPassed = false; } } - // backup if requested - bool result = true; - QString backupFilename; - QString backupPath; - if (backup) { - backupPath = g.profile[g.id()].pBackupDir(); - if (backupPath.isEmpty()) { - backupPath=g.backupDir(); + if (checkPassed) { + // backup if requested + bool result = true; + QString backupFilename; + QString backupPath; + if (backup) { + backupPath = g.profile[g.id()].pBackupDir(); + if (backupPath.isEmpty()) { + backupPath=g.backupDir(); + } + backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin"; + result = readEeprom(backupFilename, progressDialog.progress()); + sleep(2); } - backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin"; - result = readEeprom(backupFilename, progressDialog.progress()); - sleep(2); + + // flash + result = (result && writeFirmware(filename, progressDialog.progress())); + + // restore if backup requested + if (backup && result) { + sleep(2); + QString restoreFilename = generateProcessUniqueTempFileName("restore.bin"); + if (!convertEEprom(backupFilename, restoreFilename, filename)) { + QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used")); + restoreFilename = backupFilename; + } + if (!writeEeprom(restoreFilename, progressDialog.progress())) { + QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename)); + } + } + + progressDialog.progress()->setInfo(tr("Flashing done")); } - - // flash - result = (result && writeFirmware(filename, progressDialog.progress())); - - // restore if backup requested - if (backup && result) { - sleep(2); - QString restoreFilename = generateProcessUniqueTempFileName("restore.bin"); - if (!convertEEprom(backupFilename, restoreFilename, filename)) { - QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used")); - restoreFilename = backupFilename; - } - if (!writeEeprom(restoreFilename, progressDialog.progress())) { - QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename)); - } - } - - progressDialog.progress()->setInfo(tr("Flashing done")); + progressDialog.exec(); if (isTempFileName(filename)) { diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp index 7b424ec02..34d090e65 100644 --- a/companion/src/generaledit/generaledit.cpp +++ b/companion/src/generaledit/generaledit.cpp @@ -56,9 +56,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir } addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); - if (IS_ARM(firmware->getBoard())) { - addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions")); - } + addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions")); addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer")); addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware")); addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration")); diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index 1f74e2734..5404a8ccb 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -158,7 +158,7 @@ ui(new Ui::GeneralSetup) ui->usbModeLabel->hide(); ui->usbModeCB->hide(); } - + if (firmware->getCapability(HasSwitchableJack)) { ui->jackModeCB->setCurrentIndex(generalSettings.jackMode); } @@ -197,6 +197,12 @@ ui(new Ui::GeneralSetup) ui->label_OFFBright->hide(); } + if (!IS_JUMPER_T18(firmware->getBoard())) { + ui->keysBl_ChkB->hide(); + ui->keysBl_ChkB->setDisabled(true); + ui->label_KeysBl->hide(); + } + if (!firmware->getCapability(SoundMod)) { ui->soundModeCB->setDisabled(true); ui->label_soundMode->hide(); @@ -234,12 +240,7 @@ ui(new Ui::GeneralSetup) ui->memwarnChkB->setChecked(!generalSettings.disableMemoryWarning); // Default is zero=checked ui->alarmwarnChkB->setChecked(!generalSettings.disableAlarmWarning); // Default is zero=checked - if (IS_ARM(firmware->getBoard())) { - ui->rssiPowerOffWarnChkB->setChecked(!generalSettings.disableRssiPoweroffAlarm); // Default is zero=checked - } - else { - ui->rssiPowerOffWarnChkB->hide(); - } + ui->rssiPowerOffWarnChkB->setChecked(!generalSettings.disableRssiPoweroffAlarm); // Default is zero=checked if (IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) { ui->splashScreenChkB->hide(); @@ -265,7 +266,7 @@ ui(new Ui::GeneralSetup) ui->pwrOnDelayLabel->hide(); ui->pwrOnDelay->hide(); } - + setValues(); lock = false; @@ -302,13 +303,7 @@ ui(new Ui::GeneralSetup) ui->backlightColor2_label->hide(); } - if (IS_ARM(firmware->getBoard())) { - ui->switchesDelay->setValue(10*(generalSettings.switchesDelay+15)); - } - else { - ui->switchesDelay->hide(); - ui->switchesDelayLabel->hide(); - } + ui->switchesDelay->setValue(10*(generalSettings.switchesDelay+15)); ui->blAlarm_ChkB->setChecked(generalSettings.flashBeep); if (!firmware->getCapability(HasBatMeterRange)) { @@ -510,13 +505,13 @@ void GeneralSetupPanel::on_splashScreenDuration_currentIndexChanged(int index) emit modified(); } -void GeneralSetupPanel::on_pwrOnDelay_valueChanged() +void GeneralSetupPanel::on_pwrOnDelay_valueChanged(int) { generalSettings.pwrOnSpeed = 2 - ui->pwrOnDelay->value(); emit modified(); } -void GeneralSetupPanel::on_pwrOffDelay_valueChanged() +void GeneralSetupPanel::on_pwrOffDelay_valueChanged(int) { generalSettings.pwrOffSpeed = 2 - ui->pwrOffDelay->value(); emit modified(); @@ -655,7 +650,7 @@ void GeneralSetupPanel::on_backlightautoSB_editingFinished() } } -void GeneralSetupPanel::on_switchesDelay_valueChanged() +void GeneralSetupPanel::on_switchesDelay_valueChanged(int) { generalSettings.switchesDelay = (ui->switchesDelay->value() / 10) - 15; emit modified(); diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h index 34aeaaa71..43e098aee 100644 --- a/companion/src/generaledit/generalsetup.h +++ b/companion/src/generaledit/generalsetup.h @@ -65,7 +65,7 @@ class GeneralSetupPanel : public GeneralPanel void on_mavbaud_CB_currentIndexChanged(int index); void on_voiceLang_CB_currentIndexChanged(int index); void stickReverseEdited(); - void on_switchesDelay_valueChanged(); + void on_switchesDelay_valueChanged(int); void on_blAlarm_ChkB_stateChanged(); void unlockSwitchEdited(); void on_beepVolume_SL_valueChanged(); @@ -89,8 +89,8 @@ class GeneralSetupPanel : public GeneralPanel void on_contrastSB_editingFinished(); void on_registrationId_editingFinished(); - void on_pwrOnDelay_valueChanged(); - void on_pwrOffDelay_valueChanged(); + void on_pwrOnDelay_valueChanged(int); + void on_pwrOffDelay_valueChanged(int); private: Ui::GeneralSetup *ui; diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui index 98f9e76dd..7353b9c4b 100644 --- a/companion/src/generaledit/generalsetup.ui +++ b/companion/src/generaledit/generalsetup.ui @@ -554,348 +554,13 @@ - - - - - 0 - 0 - - - - 23 - - - - - - - RotEnc Navigation - - - - - - - - - - - - - - - 0 - 0 - - - - Stick reverse - - - - - - - - - - - - - This is the switch selectrion for turning on the backlight (if installed). - - - - - -1 - - - - - - - Backlight flash on alarm - - - - - - - Backlight Auto OFF after - - - - - - - Backlight Switch - - - - - - - ms - - - 200 - - - 1000 - - - 10 - - - 500 - - - - - - Voice Language - - - - - - - Hz - - - 300 - - - 1100 - - - 10 - - - 700 - - - - - - - - - 1 - - - - - - - 2 - - - - - - - 3 - - - - - - - 4 - - - - - - - - - Vario repeat at zero - - - - - - - Vario pitch at zero - - - - - - - FAI Mode - - - - - - - Backlight OFF Brightness - - - - - - - 100 - - - - - - - - 0 - 0 - - - - - - - - - - If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds. - - - sec - - - 600 - - - 5 - - - - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html> - - - 1 - - - 20 - - - 1 - - - - - - - Hz - - - 1300 - - - 2900 - - - 10 - - - 1700 - - - - Timeshift from UTC - - - - 5 - - - 100 - - - - - - - - America - - - - - Japan - - - - - Europe - - - - - - - - If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. - - - - - - - - - - - Beeper - - - - - Speaker - - - - - BeeperVoice - - - - - SpeakerVoice - - - - - - - - Backlight Brightness - - - @@ -992,24 +657,288 @@ p, li { white-space: pre-wrap; } - - + + + + + - Backlight color + Sound Mode - - + + - Vario pitch at max + - - + + + + + + 1 + + + + + + + 2 + + + + + + + 3 + + + + + + + 4 + + + + + + + + + + + + + + + This is the switch selectrion for turning on the backlight (if installed). + + + + + -1 + + + + + + + Hz + + + 300 + + + 1100 + + + 10 + + + 700 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ms + + + 200 + + + 1000 + + + 10 + + + 500 + + + + + + + + 0 + 0 + + - Speaker Pitch (spkr only) + Stick reverse + + + + + + + nnnnnnNN + + + 8 + + + + + + + + Beeper + + + + + Speaker + + + + + BeeperVoice + + + + + SpeakerVoice + + + + + + + + Backlight OFF Brightness + + + + + + + + 0 + 0 + + + + 23 + + + + + + + RotEnc Navigation + + + + + + + 5 + + + 100 + + + + + + + Backlight Switch + + + + + + + + America + + + + + Japan + + + + + Europe + + + + + + + + Vario pitch at zero + + + + + + + If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. + + + + + + + + + + Backlight Auto OFF after + + + + + + + Hz + + + 1300 + + + 2900 + + + 10 + + + 1700 + + + + + + + 100 + + + + + + + FAI Mode @@ -1044,31 +973,56 @@ p, li { white-space: pre-wrap; } - + + + + Backlight color + + + + + + + Owner Registration ID + + + + + + + + 0 + 0 + + + + + + + + + + If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds. + + + sec + + + 600 + + + 5 + + + + Country Code - - - - - - - Sound Mode - - - - - - - Speaker Volume - - - - + @@ -1098,36 +1052,96 @@ p, li { white-space: pre-wrap; } - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + - Owner Registration ID + Backlight Brightness - - - - nnnnnnNN + + + + Vario repeat at zero - - 8 + + + + + + Voice Language + + + + + + + Backlight flash on alarm + + + + + + + Vario pitch at max + + + + + + + + + + Speaker Pitch (spkr only) + + + + + + + Speaker Volume + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html> + + + 1 + + + 20 + + + 1 + + + + + + + Keys Backlight + + + + + + + diff --git a/companion/src/generaledit/hardware.cpp b/companion/src/generaledit/hardware.cpp index 4f530aa78..78d0ec75d 100644 --- a/companion/src/generaledit/hardware.cpp +++ b/companion/src/generaledit/hardware.cpp @@ -172,7 +172,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings ui->txCurrentCalibrationLabel->hide(); } - if (IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || IS_FAMILY_HORUS_OR_T16(board)) { + if (IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || IS_TARANIS_X9DP_2019(board) || IS_FAMILY_HORUS_OR_T16(board)) { ui->bluetoothMode->addItem(tr("OFF"), 0); if (IS_TARANIS_X9E(board)) { ui->bluetoothMode->addItem(tr("Enabled"), 1); diff --git a/companion/src/images/simulator/JumperT18/bottom.png b/companion/src/images/simulator/JumperT18/bottom.png new file mode 100644 index 000000000..8f0d29f7e Binary files /dev/null and b/companion/src/images/simulator/JumperT18/bottom.png differ diff --git a/companion/src/images/simulator/JumperT18/left.png b/companion/src/images/simulator/JumperT18/left.png new file mode 100755 index 000000000..4683595ec Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left.png differ diff --git a/companion/src/images/simulator/JumperT18/left_mdl.png b/companion/src/images/simulator/JumperT18/left_mdl.png new file mode 100755 index 000000000..8260dad5d Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_mdl.png differ diff --git a/companion/src/images/simulator/JumperT18/left_page.png b/companion/src/images/simulator/JumperT18/left_page.png new file mode 100755 index 000000000..5fbeafbde Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_page.png differ diff --git a/companion/src/images/simulator/JumperT18/left_sys.png b/companion/src/images/simulator/JumperT18/left_sys.png new file mode 100755 index 000000000..777f996e4 Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_sys.png differ diff --git a/companion/src/images/simulator/JumperT18/left_tele.png b/companion/src/images/simulator/JumperT18/left_tele.png new file mode 100755 index 000000000..3867d3eed Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_tele.png differ diff --git a/companion/src/images/simulator/JumperT18/right.png b/companion/src/images/simulator/JumperT18/right.png new file mode 100644 index 000000000..fced173dd Binary files /dev/null and b/companion/src/images/simulator/JumperT18/right.png differ diff --git a/companion/src/images/simulator/JumperT18/right_ent.png b/companion/src/images/simulator/JumperT18/right_ent.png new file mode 100644 index 000000000..eaf7c6acc Binary files /dev/null and b/companion/src/images/simulator/JumperT18/right_ent.png differ diff --git a/companion/src/images/simulator/JumperT18/right_rtn.png b/companion/src/images/simulator/JumperT18/right_rtn.png new file mode 100644 index 000000000..bf3d51d7d Binary files /dev/null and b/companion/src/images/simulator/JumperT18/right_rtn.png differ diff --git a/companion/src/images/simulator/JumperT18/top.png b/companion/src/images/simulator/JumperT18/top.png new file mode 100644 index 000000000..3bc1784ee Binary files /dev/null and b/companion/src/images/simulator/JumperT18/top.png differ diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 4753e0b71..9d490da39 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -26,7 +26,6 @@ #include "apppreferencesdialog.h" #include "fwpreferencesdialog.h" #include "firmwareinterface.h" -#include "fusesdialog.h" #include "downloaddialog.h" #include "printdialog.h" #include "version.h" @@ -131,15 +130,9 @@ MainWindow::MainWindow(): else { if (!g.previousVersion().isEmpty()) g.warningId(g.warningId() | AppMessages::MSG_UPGRADED); + if (g.promptProfile()) { - QTimer::singleShot(updateDelay, this, SLOT(chooseProfile())); // add an extra second to give mainwindow time to load - updateDelay += 5000; // give user time to select profile before warnings - } - else { - if (checkProfileRadioExists(g.sessionId())) - QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates())); - else - g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE); + chooseProfile(); } } QTimer::singleShot(updateDelay, this, SLOT(displayWarnings())); @@ -185,6 +178,11 @@ MainWindow::MainWindow(): if (printing) { QTimer::singleShot(0, this, SLOT(autoClose())); } + + if (checkProfileRadioExists(g.sessionId())) + QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates())); + else + g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE); } MainWindow::~MainWindow() @@ -939,10 +937,8 @@ void MainWindow::readEeprom() QString tempFile; if (IS_FAMILY_HORUS_OR_T16(board)) tempFile = generateProcessUniqueTempFileName("temp.otx"); - else if (IS_ARM(board)) - tempFile = generateProcessUniqueTempFileName("temp.bin"); else - tempFile = generateProcessUniqueTempFileName("temp.hex"); + tempFile = generateProcessUniqueTempFileName("temp.bin"); qDebug() << "MainWindow::readEeprom(): using temp file: " << tempFile; @@ -1029,14 +1025,6 @@ void MainWindow::burnConfig() void MainWindow::burnList() { burnConfigDialog bcd(this); - bcd.listAvrdudeProgrammers(); -} - -void MainWindow::burnFuses() -{ - FusesDialog *fd = new FusesDialog(this); - fd->exec(); - delete fd; } void MainWindow::compare() @@ -1065,7 +1053,7 @@ void MainWindow::about() aboutStr.append("

"); aboutStr.append(QString("Version %1, %2").arg(VERSION).arg(__DATE__)); aboutStr.append("

"); - aboutStr.append(tr("Copyright OpenTX Team") + "
© 2011-2019
"); + aboutStr.append(tr("Copyright OpenTX Team") + QString("
© 2011-%1
").arg(QString(__DATE__).right(4))); QMessageBox msgBox(this); msgBox.setWindowIcon(CompanionIcon("information.png")); msgBox.setWindowTitle(tr("About Companion")); @@ -1232,8 +1220,6 @@ void MainWindow::retranslateUi(bool showMsg) trAct(changelogAct, tr("Release notes..."), tr("Show release notes")); trAct(compareAct, tr("Compare Models..."), tr("Compare models")); trAct(editSplashAct, tr("Edit Radio Splash Image..."), tr("Edit the splash image of your Radio")); - trAct(burnListAct, tr("List programmers..."), tr("List available programmers")); - trAct(burnFusesAct, tr("Fuses..."), tr("Show fuses dialog")); trAct(readFlashAct, tr("Read Firmware from Radio"), tr("Read firmware from Radio")); trAct(writeFlashAct, tr("Write Firmware to Radio"), tr("Write firmware to Radio")); trAct(sdsyncAct, tr("Synchronize SD"), tr("SD card synchronization")); @@ -1295,7 +1281,6 @@ void MainWindow::createActions() editSplashAct = addAct("paintbrush.png", SLOT(customizeSplash())); burnListAct = addAct("list.png", SLOT(burnList())); - burnFusesAct = addAct("fuses.png", SLOT(burnFuses())); readFlashAct = addAct("read_flash.png", SLOT(readFlash())); writeFlashAct = addAct("write_flash.png", SLOT(writeFlash())); writeEepromAct = addAct("write_eeprom.png", SLOT(writeEeprom())); @@ -1400,10 +1385,6 @@ void MainWindow::createMenus() burnMenu->addAction(readFlashAct); burnMenu->addSeparator(); burnMenu->addSeparator(); - if (!IS_ARM(getCurrentBoard())) { - burnMenu->addAction(burnFusesAct); - burnMenu->addAction(burnListAct); - } windowMenu = menuBar()->addMenu(""); windowMenu->addAction(actTabbedWindows); @@ -1823,10 +1804,8 @@ void MainWindow::chooseProfile() connect(pcd, &ProfileChooserDialog::profileChanged, this, &MainWindow::loadProfileId); pcd->exec(); delete pcd; - // doi here as need to wait until dialog dismissed and current radio type is set - if (checkProfileRadioExists(g.sessionId())) - doAutoUpdates(); - else + + if (!checkProfileRadioExists(g.sessionId())) g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE); } } diff --git a/companion/src/mainwindow.h b/companion/src/mainwindow.h index 9369dacac..0be249f04 100644 --- a/companion/src/mainwindow.h +++ b/companion/src/mainwindow.h @@ -111,7 +111,6 @@ class MainWindow : public QMainWindow void readBackup(); void burnConfig(); void burnList(); - void burnFuses(); void contributors(); void sdsync(); void changelog(); @@ -210,7 +209,6 @@ class MainWindow : public QMainWindow QAction *readEepromAct; QAction *burnConfigAct; QAction *burnListAct; - QAction *burnFusesAct; QAction *writeFlashAct; QAction *readFlashAct; QAction *writeBUToRadioAct; diff --git a/companion/src/modeledit/CMakeLists.txt b/companion/src/modeledit/CMakeLists.txt index 300fb27cc..31e727081 100644 --- a/companion/src/modeledit/CMakeLists.txt +++ b/companion/src/modeledit/CMakeLists.txt @@ -42,7 +42,6 @@ set(modeledit_UIS setup_timer.ui setup_module.ui flightmode.ui - telemetry_analog.ui telemetry_customscreen.ui telemetry_sensor.ui ) diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp index 450f785fd..6442cc2fb 100644 --- a/companion/src/modeledit/channels.cpp +++ b/companion/src/modeledit/channels.cpp @@ -45,7 +45,7 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row spinbox->setSuffix("%"); } - if (IS_ARM(board) || deflt == 0 /*it's the offset*/) { + if (deflt == 0 /*it's the offset*/) { spinbox->setDecimals(1); } else { @@ -349,8 +349,11 @@ void Channels::cmCopy() void Channels::cmCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + cmCopy(); - cmClear(); + cmClear(false); } void Channels::onCustomContextMenuRequested(QPoint pos) @@ -412,10 +415,12 @@ void Channels::cmMoveDown() swapData(selectedIndex, selectedIndex + 1); } -void Channels::cmClear() +void Channels::cmClear(bool prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } model->limitData[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h index caa0fca38..d20923a35 100644 --- a/companion/src/modeledit/channels.h +++ b/companion/src/modeledit/channels.h @@ -75,7 +75,7 @@ class Channels : public ModelPanel void cmMoveUp(); void cmMoveDown(); void cmInsert(); - void cmClear(); + void cmClear(bool prompt = true); void cmClearAll(); void onCustomContextMenuRequested(QPoint pos); diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index 5759e60e6..662dc61c4 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -699,10 +699,12 @@ bool Curves::moveUpAllowed() const return selectedIndex > 0; } -void Curves::cmClear() +void Curves::cmClear(bool prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } model->curves[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); @@ -734,8 +736,10 @@ void Curves::cmCopy() void Curves::cmCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; cmCopy(); - cmClear(); + cmClear(false); } void Curves::cmDelete() diff --git a/companion/src/modeledit/curves.h b/companion/src/modeledit/curves.h index d9a5364a6..34d1a675e 100644 --- a/companion/src/modeledit/curves.h +++ b/companion/src/modeledit/curves.h @@ -81,7 +81,7 @@ class Curves : public ModelPanel void onPointSizeEdited(); void onNodeDelete(); void onCustomContextMenuRequested(QPoint pos); - void cmClear(); + void cmClear(bool prompt = true); void cmClearAll(); void cmCopy(); void cmCut(); diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index 34f05a707..36dba9c97 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -29,7 +29,7 @@ RepeatComboBox::RepeatComboBox(QWidget *parent, int & repeatParam): QComboBox(parent), repeatParam(repeatParam) { - unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10; + unsigned int step = 1; int value = repeatParam/step; setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); @@ -58,7 +58,7 @@ void RepeatComboBox::onIndexChanged(int index) void RepeatComboBox::update() { - unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10; + unsigned int step = 1; int value = repeatParam/step; if (step == 1) { value++; @@ -422,29 +422,20 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) { if (modified) cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet(); - if (IS_ARM(getCurrentBoard())) { - fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec); - fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet()); - fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString()); - if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) { - double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin()); - rng *= model->gvarData[gvidx].multiplierGet(); - fswtchParam[i]->setMinimum(-rng); - fswtchParam[i]->setMaximum(rng); - } - else { - fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec()); - fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec()); - } - fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet()); + fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec); + fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet()); + fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString()); + if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) { + double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin()); + rng *= model->gvarData[gvidx].multiplierGet(); + fswtchParam[i]->setMinimum(-rng); + fswtchParam[i]->setMaximum(rng); } else { - fswtchParam[i]->setDecimals(0); - fswtchParam[i]->setSingleStep(1); - fswtchParam[i]->setMinimum(-125); - fswtchParam[i]->setMaximum(125); - fswtchParam[i]->setValue(cfn.param); + fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec()); + fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec()); } + fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet()); widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; } else { @@ -471,7 +462,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) { widgetsMask |= CUSTOM_FUNCTION_ENABLE; } - else if (func == FuncVolume) { + else if (func == FuncVolume || func == FuncBacklight) { if (modified) cfn.param = fswtchParamT[i]->currentData().toInt(); populateFuncParamCB(fswtchParamT[i], func, cfn.param); @@ -563,12 +554,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) } Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm); } - else if (func == FuncBacklight && IS_TARANIS_PLUS(getCurrentBoard())) { - if (modified) - cfn.param = (uint8_t)fswtchBLcolor[i]->value(); - fswtchBLcolor[i]->setValue(cfn.param); - widgetsMask |= CUSTOM_FUNCTION_BL_COLOR; - } else { if (modified) cfn.param = fswtchParam[i]->value(); @@ -602,7 +587,7 @@ void CustomFunctionsPanel::update() { updateDataModels(); lock = true; - for (int i=0; iclear(); - for (unsigned int i=0; i=FuncOverrideCH1 && i<=FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) || ((i==FuncVolume || i==FuncBackgroundMusic || i==FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) || ((i==FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) || ((i==FuncPlayHaptic) && !firmware->getCapability(Haptic)) || ((i==FuncPlayBoth) && !firmware->getCapability(HasBeeper)) || ((i==FuncLogs) && !firmware->getCapability(HasSDLogs)) || - ((i==FuncSetTimer1 || i==FuncSetTimer2) && !IS_ARM(firmware->getBoard())) || ((i==FuncSetTimer3) && firmware->getCapability(Timers) < 3) || ((i==FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) || ((i>=FuncRangeCheckInternalModule && i<=FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) || @@ -691,7 +677,7 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value) else { b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i); if (i == value) { - b->setCurrentIndex(b->count()-1); + b->setCurrentIndex(b->count() - 1); } } } @@ -711,28 +697,28 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi { QStringList qs; b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model - if (function==FuncPlaySound) { + if (function == FuncPlaySound) { CustomFunctionData::populatePlaySoundParams(qs); b->addItems(qs); b->setCurrentIndex(value); } - else if (function==FuncPlayHaptic) { + else if (function == FuncPlayHaptic) { CustomFunctionData::populateHapticParams(qs); b->addItems(qs); b->setCurrentIndex(value); } - else if (function==FuncReset) { + else if (function == FuncReset) { CustomFunctionData::populateResetParams(model, b, value); } - else if (function==FuncVolume) { + else if (function == FuncVolume || function == FuncBacklight) { b->setModel(rawSrcInputsItemModel); b->setCurrentIndex(b->findData(value)); } - else if (function==FuncPlayValue) { + else if (function == FuncPlayValue) { b->setModel(rawSrcAllItemModel); b->setCurrentIndex(b->findData(value)); } - else if (function>=FuncAdjustGV1 && function<=FuncAdjustGVLast) { + else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) { switch (adjustmode) { case 1: b->setModel(rawSrcInputsItemModel); @@ -759,10 +745,12 @@ void CustomFunctionsPanel::cmMoveDown() swapData(selectedIndex, selectedIndex + 1); } -void CustomFunctionsPanel::cmClear() +void CustomFunctionsPanel::cmClear(bool prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } functions[selectedIndex].clear(); resetCBsAndRefresh(selectedIndex); @@ -771,10 +759,10 @@ void CustomFunctionsPanel::cmClear() void CustomFunctionsPanel::cmClearAll() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Special Functions. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Functions. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; - for (int i=0; icurves[fswCapability - 1].isEmpty())); + return ((selectedIndex < fswCapability - 1) && (functions[fswCapability - 1].isEmpty())); } bool CustomFunctionsPanel::moveDownAllowed() const diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h index 1c93f3e96..54a83ddcf 100644 --- a/companion/src/modeledit/customfunctions.h +++ b/companion/src/modeledit/customfunctions.h @@ -82,7 +82,7 @@ class CustomFunctionsPanel : public GenericPanel void cmMoveUp(); void cmMoveDown(); void cmInsert(); - void cmClear(); + void cmClear(bool prompt = true); void cmClearAll(); private: diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index 0745f5c84..95aaeca66 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -46,18 +46,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings))); QRegExp rx(CHAR_FOR_NAMES_REGEX); - if (IS_ARM(getCurrentBoard())) { - gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100); - gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100); - } - else { - gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, 0, 100); - gvOffsetGroup = NULL; - ui->offsetLabel->hide(); - ui->offsetGV->hide(); - ui->offsetSB->hide(); - ui->offsetCB->hide(); - } + gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100); + gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100); curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model, firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES)); diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index 1634aed3a..12082091d 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -708,10 +708,12 @@ bool FlightModePanel::moveUpAllowed() const return phaseIdx > 0; } -void FlightModePanel::cmClear() +void FlightModePanel::cmClear(bool prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } phase.clear(phaseIdx); @@ -780,8 +782,10 @@ void FlightModePanel::cmCopy() void FlightModePanel::cmCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; cmCopy(); - cmClear(); + cmClear(false); } void FlightModePanel::cmDelete() @@ -1059,7 +1063,7 @@ void FlightModePanel::gvOnCustomContextMenuRequested(QPoint pos) bool FlightModePanel::gvHasClipboardData() const { - if (gvHasDefnClipboardData() || gvHasValueClipboardData()) + if ((phaseIdx == 0 && gvHasDefnClipboardData() && gvHasAllValuesClipboardData()) || (phaseIdx > 0 && gvHasValueClipboardData())) return true; return false; } @@ -1092,6 +1096,20 @@ bool FlightModePanel::gvHasValueClipboardData(QByteArray * data) const return false; } +bool FlightModePanel::gvHasAllValuesClipboardData(QByteArray * data) const +{ + const QClipboard * clipboard = QApplication::clipboard(); + const QMimeData * mimeData = clipboard->mimeData(); + if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_ALL_VALUES)) { + if (data) { + data->clear(); + data->append(mimeData->data(MIMETYPE_GVAR_ALL_VALUES)); + } + return true; + } + return false; +} + bool FlightModePanel::gvDeleteAllowed() const { return phaseIdx == 0; @@ -1124,11 +1142,13 @@ bool FlightModePanel::gvMoveUpAllowed() const return (phaseIdx == 0 && gvIdx > 0); } -void FlightModePanel::gvCmClear() +void FlightModePanel::gvCmClear(bool prompt) { if (phaseIdx == 0) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear selected Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } model->gvarData[gvIdx].clear(); for (int i = 0; i < fmCount; i++) { model->flightModeData[i].gvars[gvIdx] = model->flightModeData[i].linkedGVarFlightModeZero(i); @@ -1136,6 +1156,10 @@ void FlightModePanel::gvCmClear() model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx); } else { + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx); } emit datachanged(); @@ -1173,38 +1197,58 @@ void FlightModePanel::gvCmCopy() if (phaseIdx == 0) { data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData)); mimeData->setData(MIMETYPE_GVAR_PARAMS, data); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); + + data.clear(); + for (int j = 0; j < fmCount; j++) { + data.append((char*)&model->flightModeData[j].gvars[gvIdx], sizeof(phase.gvars[0])); + } + mimeData->setData(MIMETYPE_GVAR_ALL_VALUES, data); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); + + mimeData->removeFormat(MIMETYPE_GVAR_VALUE); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } else { mimeData->removeFormat(MIMETYPE_GVAR_PARAMS); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); + + mimeData->removeFormat(MIMETYPE_GVAR_ALL_VALUES); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); + + data.clear(); + int val = phase.gvars[gvIdx]; + if (model->isGVarLinked(phaseIdx, gvIdx)) + val = GVAR_MAX_VALUE + 1 + model->getGVarFlightModeIndex(phaseIdx, gvIdx); // store index in case paste is to another flight mode + data.setNum(val); + mimeData->setData(MIMETYPE_GVAR_VALUE, data); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - int val = phase.gvars[gvIdx]; - if (model->isGVarLinked(phaseIdx, gvIdx)) - val = GVAR_MAX_VALUE + 1 + model->getGVarFlightModeIndex(phaseIdx, gvIdx); // store index in case paste is to another flight mode - data.setNum(val); - mimeData->setData(MIMETYPE_GVAR_VALUE, data); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } void FlightModePanel::gvCmCut() { - gvCmCopy(); - if (phaseIdx > 0) { - gvCmClear(); + if (phaseIdx == 0) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; } else { - model->gvarData[gvIdx].clear(); - phase.gvars[gvIdx] = 0; - model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx); - emit datachanged(); - emit modified(); + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; } + + gvCmCopy(); + gvCmClear(false); } void FlightModePanel::gvCmDelete() { if (phaseIdx > 0) return; + + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + int maxidx = gvCount - 1; for (int i = gvIdx; i < maxidx; i++) { memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData)); @@ -1254,11 +1298,20 @@ void FlightModePanel::gvCmMoveUp() void FlightModePanel::gvCmPaste() { QByteArray data; - if (phaseIdx == 0 && gvHasDefnClipboardData(&data)) { - GVarData *gvd = &model->gvarData[gvIdx]; - memcpy(gvd, data.constData(), sizeof(GVarData)); + if (phaseIdx == 0) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Paste to selected Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + if (gvHasDefnClipboardData(&data)) { + memcpy(&model->gvarData[gvIdx], data.constData(), sizeof(GVarData)); + } + if (gvHasAllValuesClipboardData(&data)) { + for (int j = 0; j < fmCount; j++) { + int *gvar = &model->flightModeData[j].gvars[gvIdx]; + memcpy(gvar, data.mid(j * sizeof(phase.gvars[0]), sizeof(phase.gvars[0])).constData(), sizeof(phase.gvars[0])); + } + } } - if (gvHasValueClipboardData(&data)) { + else if (gvHasValueClipboardData(&data)) { int val = data.toInt(); if (val > GVAR_MAX_VALUE) { if (phaseIdx > 0) diff --git a/companion/src/modeledit/flightmodes.h b/companion/src/modeledit/flightmodes.h index 1986f1e46..61e25c59a 100644 --- a/companion/src/modeledit/flightmodes.h +++ b/companion/src/modeledit/flightmodes.h @@ -29,6 +29,7 @@ class RawSwitchFilterItemModel; constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode"; constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params"; constexpr char MIMETYPE_GVAR_VALUE[] = "application/x-companion-gvar-value"; +constexpr char MIMETYPE_GVAR_ALL_VALUES[] = "application/x-companion-gvar-all-values"; namespace Ui { class FlightMode; @@ -67,7 +68,7 @@ class FlightModePanel : public ModelPanel void phaseREValue_editingFinished(); void phaseREUse_currentIndexChanged(int index); void onCustomContextMenuRequested(QPoint pos); - void cmClear(); + void cmClear(bool prompt = true); void cmClearAll(); void cmCopy(); void cmCut(); @@ -77,7 +78,7 @@ class FlightModePanel : public ModelPanel void cmMoveDown(); void cmMoveUp(); void gvOnCustomContextMenuRequested(QPoint pos); - void gvCmClear(); + void gvCmClear(bool prompt = true); void gvCmClearAll(); void gvCmCopy(); void gvCmCut(); @@ -127,6 +128,7 @@ class FlightModePanel : public ModelPanel bool gvHasClipboardData() const; bool gvHasDefnClipboardData(QByteArray * data = nullptr) const; bool gvHasValueClipboardData(QByteArray * data = nullptr) const; + bool gvHasAllValuesClipboardData(QByteArray * data = nullptr) const; bool gvDeleteAllowed() const; bool gvInsertAllowed() const; bool gvMoveDownAllowed() const; diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp index 806de54fc..2e65c788c 100644 --- a/companion/src/modeledit/inputs.cpp +++ b/companion/src/modeledit/inputs.cpp @@ -227,26 +227,27 @@ void InputsPanel::setSelectedByExpoList(QList list) } } -void InputsPanel::exposDelete(bool ask) +void InputsPanel::exposDelete(bool prompt) { QList list = createExpoListFromSelected(); if (list.isEmpty()) return; - QMessageBox::StandardButton ret = QMessageBox::No; - - if (ask) - ret = QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Delete selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No); - - if ((ret == QMessageBox::Yes) || (!ask)) { - exposDeleteList(list, ask); - emit modified(); - update(); + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete selected Input lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; } + + exposDeleteList(list, prompt); + emit modified(); + update(); } void InputsPanel::exposCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut selected Input lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + exposCopy(); exposDelete(false); } @@ -317,7 +318,6 @@ void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx) } } - void InputsPanel::exposPaste() { const QClipboard *clipboard = QApplication::clipboard(); @@ -515,7 +515,7 @@ void InputsPanel::exposDeleteList(QList list, bool clearName) void InputsPanel::clearExpos() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Input lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { model->clearInputs(); for (int i = 0; i < inputsCount; i++) { model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, i); @@ -559,7 +559,7 @@ bool InputsPanel::cmInputMoveUpAllowed() const void InputsPanel::cmInputClear() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all lines for the selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) { @@ -574,7 +574,7 @@ void InputsPanel::cmInputClear() void InputsPanel::cmInputDelete() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete all lines for the selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; for (int i = 0; i < CPN_MAX_EXPOS; i++) { diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h index 884573fef..9922f2873 100644 --- a/companion/src/modeledit/inputs.h +++ b/companion/src/modeledit/inputs.h @@ -46,7 +46,7 @@ class InputsPanel : public ModelPanel void expolistWidget_customContextMenuRequested(QPoint pos); void expolistWidget_doubleClicked(QModelIndex index); void expolistWidget_KeyPress(QKeyEvent *event); - void exposDelete(bool ask=true); + void exposDelete(bool prompt = true); void exposCut(); void exposCopy(); void exposPaste(); diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp index 13e20b8f6..e70d63568 100644 --- a/companion/src/modeledit/logicalswitches.cpp +++ b/companion/src/modeledit/logicalswitches.cpp @@ -479,10 +479,6 @@ void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b) int func = order[i]; if (func == LS_FN_NEQUAL || func == LS_FN_EGREATER || func == LS_FN_ELESS) continue; - if (!IS_ARM(firmware->getBoard())) { - if (func == LS_FN_VEQUAL || func == LS_FN_EDGE) - continue; - } b->addItem(LogicalSwitchData(func).funcToString(), func); } b->setMaxVisibleItems(10); @@ -490,27 +486,7 @@ void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b) void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b) { - if (IS_ARM(firmware->getBoard())) { - b->setModel(rawSwitchItemModel); - } - else { - RawSwitch item; - - b->clear(); - - item = RawSwitch(SWITCH_TYPE_NONE); - b->addItem(item.toString(), item.toValue()); - - for (int i=1; i <= Boards::getCapability(firmware->getBoard(), Board::SwitchPositions); i++) { - item = RawSwitch(SWITCH_TYPE_SWITCH, i); - b->addItem(item.toString(), item.toValue()); - } - - for (int i=1; i<=6; i++) { - item = RawSwitch(SWITCH_TYPE_VIRTUAL, i); - b->addItem(item.toString(), item.toValue()); - } - } + b->setModel(rawSwitchItemModel); b->setVisible(true); } @@ -557,8 +533,10 @@ void LogicalSwitchesPanel::cmCopy() void LogicalSwitchesPanel::cmCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Logical Switch. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; cmCopy(); - cmClear(); + cmClear(false); } // TODO make something generic here! @@ -621,8 +599,13 @@ void LogicalSwitchesPanel::cmMoveDown() swapData(selectedIndex, selectedIndex + 1); } -void LogicalSwitchesPanel::cmClear() +void LogicalSwitchesPanel::cmClear(bool prompt) { + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Logical Switch. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } + model->logicalSw[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); update(); diff --git a/companion/src/modeledit/logicalswitches.h b/companion/src/modeledit/logicalswitches.h index 2aea300c5..62aa69f30 100644 --- a/companion/src/modeledit/logicalswitches.h +++ b/companion/src/modeledit/logicalswitches.h @@ -59,7 +59,7 @@ class LogicalSwitchesPanel : public ModelPanel void cmMoveUp(); void cmMoveDown(); void cmInsert(); - void cmClear(); + void cmClear(bool prompt = true); void cmClearAll(); private: diff --git a/companion/src/modeledit/mixes.cpp b/companion/src/modeledit/mixes.cpp index c92105ec6..4d0f5f4cd 100644 --- a/companion/src/modeledit/mixes.cpp +++ b/companion/src/modeledit/mixes.cpp @@ -253,28 +253,27 @@ void MixesPanel::setSelectedByMixList(QList list) } -void MixesPanel::mixersDelete(bool ask) +void MixesPanel::mixersDelete(bool prompt) { QList list = createMixListFromSelected(); - if(list.isEmpty()) return; + if(list.isEmpty()) + return; - QMessageBox::StandardButton ret = QMessageBox::No; - - if(ask) { - ret = QMessageBox::warning(this, "companion", - tr("Delete Selected Mixes?"), - QMessageBox::Yes | QMessageBox::No); + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete selected Mix lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; } - if ((ret == QMessageBox::Yes) || (!ask)) { - mixersDeleteList(list); - emit modified(); - update(); - } + mixersDeleteList(list); + emit modified(); + update(); } void MixesPanel::mixersCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut selected Mix lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + mixersCopy(); mixersDelete(false); } diff --git a/companion/src/modeledit/mixes.h b/companion/src/modeledit/mixes.h index 46a51a21a..95765465e 100644 --- a/companion/src/modeledit/mixes.h +++ b/companion/src/modeledit/mixes.h @@ -39,7 +39,7 @@ class MixesPanel : public ModelPanel private slots: // TODO all slots? void clearMixes(); - void mixersDelete(bool ask=true); + void mixersDelete(bool prompt = true); void mixersCut(); void mixersCopy(); void mixersPaste(); diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index 59fb408c4..af3166c7f 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -65,7 +65,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw s1.report("LS"); addTab(new CustomFunctionsPanel(this, &radioData.models[modelId], radioData.generalSettings, firmware), tr("Special Functions")); s1.report("CF"); - if (firmware->getCapability(Telemetry) & TM_HASTELEMETRY) + if (firmware->getCapability(Telemetry)) addTab(new TelemetryPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Telemetry")); onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 43eaf11fe..5d4dfec79 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -36,7 +36,6 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge timer(timer), ui(new Ui::Timer) { - Board::Type board = firmware->getBoard(); ui->setupUi(this); @@ -65,10 +64,8 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge ui->countdownBeep->setField(timer.countdownBeep, this); ui->countdownBeep->addItem(tr("Silent"), TimerData::COUNTDOWN_SILENT); ui->countdownBeep->addItem(tr("Beeps"), TimerData::COUNTDOWN_BEEPS); - if (IS_ARM(board) || IS_2560(board)) { - ui->countdownBeep->addItem(tr("Voice"), TimerData::COUNTDOWN_VOICE); - ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC); - } + ui->countdownBeep->addItem(tr("Voice"), TimerData::COUNTDOWN_VOICE); + ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC); ui->value->setMaximumTime(firmware->getMaxTimerStart()); @@ -192,6 +189,8 @@ void TimerPanel::on_name_editingFinished() #define MASK_SBUSPPM_FIELDS (1<<11) #define MASK_SUBTYPES (1<<12) #define MASK_ACCESS (1<<13) +#define MASK_RX_FREQ (1<<14) +#define MASK_RF_POWER (1<<15) quint8 ModulePanel::failsafesValueDisplayType = ModulePanel::FAILSAFE_DISPLAY_PERCENT; @@ -207,7 +206,7 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul ui->label_module->setText(ModuleData::indexToString(moduleIdx, firmware)); if (moduleIdx < 0) { - if (!IS_TARANIS(firmware->getBoard())) { + if (!IS_TARANIS(firmware->getBoard()) || IS_ACCESS_RADIO(firmware->getBoard(), Firmware::getCurrentVariant()->getId())) { ui->trainerMode->setItemData(TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, 0, Qt::UserRole - 1); ui->trainerMode->setItemData(TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, 0, Qt::UserRole - 1); ui->trainerMode->setItemData(TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, 0, Qt::UserRole - 1); @@ -271,7 +270,7 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul connect(ui->multiProtocol, static_cast(&QComboBox::currentIndexChanged), this, &ModulePanel::onMultiProtocolChanged); connect(this, &ModulePanel::channelsRangeChanged, this, &ModulePanel::setupFailsafes); connect(ui->btnGrpValueType, static_cast(&QButtonGroup::buttonClicked), this, &ModulePanel::onFailsafesDisplayValueTypeChanged); - + connect(ui->rxFreq, static_cast(&QSpinBox::valueChanged), this, &ModulePanel::onRfFreqChanged); connect(ui->clearRx1, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked())); connect(ui->clearRx2, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked())); connect(ui->clearRx3, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked())); @@ -391,7 +390,7 @@ void ModulePanel::update() mask |= MASK_PROTOCOL; switch (protocol) { case PULSES_PXX_R9M: - mask |= MASK_R9M | MASK_SUBTYPES; + mask |= MASK_R9M | MASK_RF_POWER | MASK_SUBTYPES; case PULSES_ACCESS_R9M: case PULSES_ACCESS_R9M_LITE: case PULSES_ACCESS_R9M_LITE_PRO: @@ -425,6 +424,8 @@ void ModulePanel::update() max_rx_num = 20; break; case PULSES_CROSSFIRE: + mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER; + case PULSES_GHOST: mask |= MASK_CHANNELS_RANGE; module.channelsCount = 16; break; @@ -450,6 +451,11 @@ void ModulePanel::update() if (pdef.hasFailsafe || (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_FRSKY && (module.subType == 0 || module.subType == 2 || module.subType > 3 ))) mask |= MASK_FAILSAFES; break; + case PULSES_AFHDS3: + module.channelsCount = 18; + mask |= MASK_CHANNELS_RANGE| MASK_CHANNELS_COUNT | MASK_FAILSAFES; + mask |= MASK_SUBTYPES | MASK_RX_FREQ | MASK_RF_POWER; + break; case PULSES_OFF: break; default: @@ -516,16 +522,16 @@ void ModulePanel::update() } // R9M options - ui->r9mPower->setVisible(mask & MASK_R9M); - ui->label_r9mPower->setVisible(mask & MASK_R9M); + ui->r9mPower->setVisible(mask & MASK_RF_POWER); + ui->label_r9mPower->setVisible(mask & MASK_RF_POWER); ui->warning_r9mPower->setVisible((mask & MASK_R9M) && module.subType == MODULE_SUBTYPE_R9M_EU); ui->warning_r9mFlex->setVisible((mask & MASK_R9M) && module.subType > MODULE_SUBTYPE_R9M_EU); - if (mask & MASK_R9M) { + if (mask & MASK_RF_POWER) { const QSignalBlocker blocker(ui->r9mPower); ui->r9mPower->clear(); - ui->r9mPower->addItems(ModuleData::powerValueStrings(module.subType, firmware)); - ui->r9mPower->setCurrentIndex(module.pxx.power); + ui->r9mPower->addItems(ModuleData::powerValueStrings(protocol, module.subType, firmware)); + ui->r9mPower->setCurrentIndex(mask & MASK_R9M ? module.pxx.power : module.afhds3.rfPower); } // module subtype @@ -542,6 +548,9 @@ void ModulePanel::update() if (firmware->getCapability(HasModuleR9MFlex)) i = 2; break; + case PULSES_AFHDS3: + numEntries = 4; + break; default: break; } @@ -563,7 +572,7 @@ void ModulePanel::update() ui->lowPower->setVisible(mask & MASK_MULTIMODULE); ui->autoBind->setVisible(mask & MASK_MULTIMODULE); if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2) - ui->autoBind->setText(tr("Autodetect Format")); + ui->autoBind->setVisible(false); else ui->autoBind->setText(tr("Bind on channel")); @@ -606,6 +615,8 @@ void ModulePanel::update() // Failsafes ui->label_failsafeMode->setVisible(mask & MASK_FAILSAFES); ui->failsafeMode->setVisible(mask & MASK_FAILSAFES); + //hide reciever mode for afhds3 + qobject_cast(ui->failsafeMode->view())->setRowHidden(FAILSAFE_RECEIVER, protocol == PULSES_AFHDS3); if ((mask & MASK_FAILSAFES) && module.failsafeMode == FAILSAFE_CUSTOM) { if (ui->failsafesGroupBox->isHidden()) { @@ -635,6 +646,9 @@ void ModulePanel::update() } } } + + ui->label_rxFreq->setVisible((mask & MASK_RX_FREQ)); + ui->rxFreq->setVisible((mask & MASK_RX_FREQ)); } void ModulePanel::on_trainerMode_currentIndexChanged(int index) @@ -666,9 +680,14 @@ void ModulePanel::on_ppmPolarity_currentIndexChanged(int index) void ModulePanel::on_r9mPower_currentIndexChanged(int index) { - if (!lock && module.pxx.power != (unsigned int)index) { - module.pxx.power = index; - emit modified(); + if (!lock) { + + if (module.protocol == PULSES_AFHDS3 && module.afhds3.rfPower != (unsigned int)index) { + module.afhds3.rfPower = index; + emit modified(); + } + else if(module.pxx.power != (unsigned int)index) + module.pxx.power = index; } } @@ -766,12 +785,21 @@ void ModulePanel::onSubTypeChanged() if (!lock && module.subType != type) { lock=true; module.subType = type; - update(); + if (module.protocol != PULSES_AFHDS3) { + update(); + } emit modified(); lock = false; } } +void ModulePanel::onRfFreqChanged(int freq) { + if (module.afhds3.rxFreq != (unsigned int)freq) { + module.afhds3.rxFreq = (unsigned int)freq; + emit modified(); + } +} + void ModulePanel::on_disableTelem_stateChanged(int state) { module.multi.disableTelemetry = (state == Qt::Checked); @@ -1176,13 +1204,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge ui->potWarningMode->hide(); } - if (IS_ARM(board)) { - ui->trimsDisplay->setField(model.trimsDisplay, this); - } - else { - ui->labelTrimsDisplay->hide(); - ui->trimsDisplay->hide(); - } + ui->trimsDisplay->setField(model.trimsDisplay, this); for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) { modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i); @@ -1254,6 +1276,14 @@ void SetupPanel::on_throttleSource_currentIndexChanged(int index) } } +void SetupPanel::on_throttleTrimSwitch_currentIndexChanged(int index) +{ + if (!lock) { + model->thrTrimSwitch = ui->throttleTrimSwitch->currentData().toUInt(); + emit modified(); + } +} + void SetupPanel::on_name_editingFinished() { if (QString(model->name) != ui->name->text()) { @@ -1326,11 +1356,29 @@ void SetupPanel::populateThrottleSourceCB() lock = false; } +void SetupPanel::populateThrottleTrimSwitchCB() +{ + Board::Type board = firmware->getBoard(); + lock = true; + ui->throttleTrimSwitch->clear(); + int idx=0; + for (int i=0; ithrottleTrimSwitch->addItem(trim, idx); + } + + int thrTrimSwitchIdx = ui->throttleTrimSwitch->findData(model->thrTrimSwitch); + ui->throttleTrimSwitch->setCurrentIndex(thrTrimSwitchIdx); + lock = false; +} + void SetupPanel::update() { ui->name->setText(model->name); ui->throttleReverse->setChecked(model->throttleReversed); populateThrottleSourceCB(); + populateThrottleTrimSwitchCB(); ui->throttleWarning->setChecked(!model->disableThrottleWarning); ui->trimIncrement->setCurrentIndex(model->trimInc+2); ui->throttleTrim->setChecked(model->thrTrim); @@ -1570,10 +1618,12 @@ bool SetupPanel::moveTimerUpAllowed() const return selectedTimerIndex > 0; } -void SetupPanel::cmTimerClear() +void SetupPanel::cmTimerClear(bool prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } model->timers[selectedTimerIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex); @@ -1605,8 +1655,10 @@ void SetupPanel::cmTimerCopy() void SetupPanel::cmTimerCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; cmTimerCopy(); - cmTimerClear(); + cmTimerClear(false); } void SetupPanel::cmTimerDelete() diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 1470e4e2f..e0c3df507 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -97,6 +97,7 @@ class ModulePanel : public ModelPanel void onFailsafeUsecChanged(int value); void onFailsafePercentChanged(double value); void onFailsafesDisplayValueTypeChanged(int type); + void onRfFreqChanged(int freq); void updateFailsafe(unsigned channel); void on_optionValue_editingFinished(); void onClearAccessRxClicked(); @@ -137,6 +138,7 @@ class SetupPanel : public ModelPanel private slots: void on_name_editingFinished(); void on_throttleSource_currentIndexChanged(int index); + void on_throttleTrimSwitch_currentIndexChanged(int index); void on_throttleTrim_toggled(bool checked); void on_extendedLimits_toggled(bool checked); void on_extendedTrims_toggled(bool checked); @@ -153,7 +155,7 @@ class SetupPanel : public ModelPanel void on_potWarningMode_currentIndexChanged(int index); void on_editText_clicked(); void onTimerCustomContextMenuRequested(QPoint pos); - void cmTimerClear(); + void cmTimerClear(bool prompt = true); void cmTimerClearAll(); void cmTimerCopy(); void cmTimerCut(); @@ -175,6 +177,7 @@ class SetupPanel : public ModelPanel void updatePotWarnings(); void updateBeepCenter(); void populateThrottleSourceCB(); + void populateThrottleTrimSwitchCB(); int timersCount; int selectedTimerIndex; bool hasTimerClipboardData(QByteArray * data = nullptr) const; diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui index fc499ad63..8b2409191 100644 --- a/companion/src/modeledit/setup.ui +++ b/companion/src/modeledit/setup.ui @@ -6,7 +6,7 @@ 0 0 - 893 + 1007 405
@@ -32,22 +32,6 @@
- - - - - 50 - false - - - - Top LCD Timer - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -149,6 +133,106 @@ + + + + + 75 + true + + + + Model + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Timer 3 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + 50 + false + + + + Throttle Source + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Trim Step + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Trims Display + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + 50 + false + + + + Top LCD Timer + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -171,6 +255,66 @@ + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + 50 + false + + + + Timer 2 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + @@ -275,44 +419,8 @@ - - - - - 75 - true - - - - Model - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + + Qt::Horizontal @@ -334,86 +442,13 @@ - - - - Qt::Horizontal - - - - - - - - Qt::LeftToRight - - - Display Checklist - - - - - - - - 0 - 0 - - - - - Never - - - - - On change - - - - - Always - - - - - - - - Qt::LeftToRight - - - Throttle Trim Idle Only - - - - - - - Global Functions - - - - - - - Qt::LeftToRight - - - Throttle Warning - - - - - - - - 0 - 0 - - - + + + 6 + + + @@ -450,6 +485,81 @@ + + + + + 0 + 0 + + + + + Never + + + + + On change + + + + + Always + + + + + + + + Qt::LeftToRight + + + Throttle Warning + + + + + + + Qt::LeftToRight + + + Display Checklist + + + + + + + Global Functions + + + + + + + + 0 + 0 + + + + Edit Checklist... + + + + + + + Qt::LeftToRight + + + Throttle Trim Idle Only + + + @@ -466,16 +576,10 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi - - - - - 0 - 0 - - + + - Edit Checklist... + Throttle trim switch @@ -499,7 +603,17 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi - + + + + + 0 + 0 + + + + + Qt::Horizontal @@ -514,107 +628,6 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi - - - - - - - 50 - false - - - - Throttle Source - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Trim Step - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Trims Display - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - Qt::Horizontal - - - - - - - - 50 - false - - - - Timer 2 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Timer 3 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - -
diff --git a/companion/src/modeledit/setup_module.ui b/companion/src/modeledit/setup_module.ui index c0a54d024..654af2a54 100644 --- a/companion/src/modeledit/setup_module.ui +++ b/companion/src/modeledit/setup_module.ui @@ -126,6 +126,12 @@ 0 + + + 100 + 0 + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -173,6 +179,15 @@ 0 + + + 100 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -214,6 +229,12 @@ 0 + + + 100 + 0 + + QComboBox::AdjustToContents @@ -417,6 +438,7 @@ + @@ -485,6 +507,12 @@ 0 + + + 80 + 0 + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -529,6 +557,12 @@ 0 + + + 80 + 0 + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -573,6 +607,15 @@ 0 + + + 80 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + ms @@ -617,19 +660,58 @@ 0 + + + 80 + 0 + + QComboBox::AdjustToContents + + + + RX Frequency + + + + + + Option value + + + + + + + + 0 + 0 + + + + + 80 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + Output type - + @@ -652,21 +734,7 @@ - - - - Option value - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + Qt::Horizontal @@ -679,6 +747,34 @@ + + + + + 0 + 0 + + + + + 80 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Hz + + + 50 + + + 400 + + + @@ -711,11 +807,17 @@ - + 0 0 + + + 180 + 0 + + QComboBox::AdjustToContents @@ -754,11 +856,17 @@ - + 0 0 + + + 150 + 0 + + QComboBox::AdjustToContents @@ -774,11 +882,17 @@ - + 0 0 + + + 150 + 0 + + QComboBox::AdjustToContents @@ -847,11 +961,17 @@ - + 0 0 + + + 150 + 0 + + QComboBox::AdjustToContents @@ -901,11 +1021,17 @@ - + 0 0 + + + 150 + 0 + + QComboBox::AdjustToContents @@ -934,17 +1060,17 @@ Master/SBUS in battery compartment - + Master/Bluetooth - + Slave/Bluetooth - + Master/Multi diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp index 83565c03e..b34caa89e 100644 --- a/companion/src/modeledit/telemetry.cpp +++ b/companion/src/modeledit/telemetry.cpp @@ -20,7 +20,6 @@ #include "telemetry.h" #include "ui_telemetry.h" -#include "ui_telemetry_analog.h" #include "ui_telemetry_customscreen.h" #include "ui_telemetry_sensor.h" #include "helpers.h" @@ -29,294 +28,6 @@ #include -TelemetryAnalog::TelemetryAnalog(QWidget *parent, FrSkyChannelData & analog, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): - ModelPanel(parent, model, generalSettings, firmware), - ui(new Ui::TelemetryAnalog), - analog(analog), - lock(false) -{ - ui->setupUi(this); - - float ratio = analog.getRatio(); - - if (analog.type==0 || analog.type==1 || analog.type==2) { - ui->RatioSB->setDecimals(1); - ui->RatioSB->setMaximum(25.5*firmware->getCapability(TelemetryMaxMultiplier)); - } - else { - ui->RatioSB->setDecimals(0); - ui->RatioSB->setMaximum(255*firmware->getCapability(TelemetryMaxMultiplier)); - } - ui->RatioSB->setValue(ratio); - - update(); - - ui->UnitCB->setCurrentIndex(analog.type); - ui->alarm1LevelCB->setCurrentIndex(analog.alarms[0].level); - ui->alarm1GreaterCB->setCurrentIndex(analog.alarms[0].greater); - ui->alarm2LevelCB->setCurrentIndex(analog.alarms[1].level); - ui->alarm2GreaterCB->setCurrentIndex(analog.alarms[1].greater); - - if (!(firmware->getCapability(Telemetry) & TM_HASOFFSET)) { - ui->CalibSB->hide(); - ui->CalibLabel->hide(); - } - else { - ui->label_Max->setText(tr("Range")); - } - - disableMouseScrolling(); -} - -void TelemetryAnalog::update() -{ - float ratio = analog.getRatio(); - float step = ratio / 255; - float mini = (ratio * analog.offset) / 255; - float maxi = mini + ratio; - - ui->alarm1ValueSB->setDecimals(2); - ui->alarm1ValueSB->setSingleStep(step); - ui->alarm1ValueSB->setMinimum(mini); - ui->alarm1ValueSB->setMaximum(maxi); - ui->alarm1ValueSB->setValue(mini + step*analog.alarms[0].value); - - ui->alarm2ValueSB->setDecimals(2); - ui->alarm2ValueSB->setSingleStep(step); - ui->alarm2ValueSB->setMinimum(mini); - ui->alarm2ValueSB->setMaximum(maxi); - ui->alarm2ValueSB->setValue(mini + step*analog.alarms[1].value); - - ui->CalibSB->setDecimals(2); - ui->CalibSB->setMaximum(step*127); - ui->CalibSB->setMinimum(-step*128); - ui->CalibSB->setSingleStep(step); - ui->CalibSB->setValue(mini); -} - -static int findmult(float value, float base) -{ - int vvalue = value*10; - int vbase = base*10; - vvalue--; - - int mult = 0; - for (int i=8; i>=0; i--) { - if (vvalue/vbase >= (1<RatioSB->setDecimals(1); - ui->RatioSB->setMaximum(25.5*firmware->getCapability(TelemetryMaxMultiplier)); - break; - default: - ui->RatioSB->setDecimals(0); - ui->RatioSB->setMaximum(255*firmware->getCapability(TelemetryMaxMultiplier)); - break; - } - ui->RatioSB->setValue(ratio); - update(); - emit modified(); -} - -void TelemetryAnalog::on_RatioSB_valueChanged() -{ - if (!lock) { - if (analog.type==0 || analog.type==1 || analog.type==2) { - analog.multiplier = findmult(ui->RatioSB->value(), 25.5); - float singlestep =(1<RatioSB->setSingleStep(singlestep); - ui->RatioSB->setValue(round(ui->RatioSB->value()/singlestep)*singlestep); - lock=false; - } - else { - analog.multiplier = findmult(ui->RatioSB->value(), 255); - float singlestep = (1<RatioSB->setSingleStep(singlestep); - ui->RatioSB->setValue(round(ui->RatioSB->value()/singlestep)*singlestep); - lock = false; - } - emit modified(); - } -} - -void TelemetryAnalog::on_RatioSB_editingFinished() -{ - if (!lock) { - float ratio, calib, alarm1value,alarm2value; - - if (analog.type==0 || analog.type==1 || analog.type==2) { - analog.multiplier = findmult(ui->RatioSB->value(), 25.5); - ui->CalibSB->setSingleStep((1<alarm1ValueSB->setSingleStep((1<alarm2ValueSB->setSingleStep((1<RatioSB->value()*10))/(1 <RatioSB->value(), 255); - ui->CalibSB->setSingleStep(1<alarm1ValueSB->setSingleStep(1<alarm2ValueSB->setSingleStep(1<RatioSB->value()/(1 << analog.multiplier)); - } - ui->CalibSB->setMaximum((ui->RatioSB->value()*127)/255); - ui->CalibSB->setMinimum((ui->RatioSB->value()*-128)/255); - ui->alarm1ValueSB->setMaximum(ui->RatioSB->value()); - ui->alarm2ValueSB->setMaximum(ui->RatioSB->value()); - repaint(); - ratio=analog.ratio * (1 << analog.multiplier); - calib=ui->CalibSB->value(); - alarm1value=ui->alarm1ValueSB->value(); - alarm2value=ui->alarm2ValueSB->value(); - if (analog.type==0) { - calib*=10; - alarm1value*=10; - alarm2value*=10; - } - if (calib>0) { - if (calib>((ratio*127)/255)) { - analog.offset=127; - } - else { - analog.offset=round(calib*255/ratio); - } - } - if (calib<0) { - if (calib<((ratio*-128)/255)) { - analog.offset=-128; - } - else { - analog.offset=round(calib*255/ratio); - } - } - analog.alarms[0].value=round((alarm1value*255-analog.offset*(analog.ratio<CalibSB->value()/ratio)); - calib=ratio*analog.offset/255.0; - alarm1value=ui->alarm1ValueSB->value(); - alarm2value=ui->alarm2ValueSB->value(); - if (alarm1value(ratio+calib)) { - alarm1value=ratio+calib; - } - if (alarm2value(ratio+calib)) { - alarm2value=ratio+calib; - } - analog.alarms[0].value=round(((alarm1value-calib)*255)/ratio); - analog.alarms[1].value=round(((alarm2value-calib)*255)/ratio); - } - else { - analog.offset=0; - analog.alarms[0].value=0; - analog.alarms[1].value=0; - } - update(); - emit modified(); -} - -void TelemetryAnalog::on_alarm1LevelCB_currentIndexChanged(int index) -{ - analog.alarms[0].level = index; - emit modified(); -} - - -void TelemetryAnalog::on_alarm1GreaterCB_currentIndexChanged(int index) -{ - analog.alarms[0].greater = index; - emit modified(); -} - -void TelemetryAnalog::on_alarm1ValueSB_editingFinished() -{ - float ratio = analog.getRatio(); - float calib, alarm1value; - - calib=analog.offset; - alarm1value=ui->alarm1ValueSB->value(); - - if (alarm1value<((calib*ratio)/255)) { - analog.alarms[0].value=0; - } - else if (alarm1value>(ratio+(calib*ratio)/255)) { - analog.alarms[0].value=255; - } - else { - analog.alarms[0].value = round((alarm1value-((calib*ratio)/255))/ratio*255); - } - update(); - emit modified(); -} - -void TelemetryAnalog::on_alarm2LevelCB_currentIndexChanged(int index) -{ - analog.alarms[1].level = index; - emit modified(); -} - -void TelemetryAnalog::on_alarm2GreaterCB_currentIndexChanged(int index) -{ - analog.alarms[1].greater = index; - emit modified(); -} - -void TelemetryAnalog::on_alarm2ValueSB_editingFinished() -{ - float calib, alarm2value; - float ratio = analog.getRatio(); - calib = analog.offset; - alarm2value = ui->alarm2ValueSB->value(); - if (alarm2value<((calib*ratio)/255)) { - analog.alarms[1].value=0; - } - else if (alarm2value>(ratio+(calib*ratio)/255)) { - analog.alarms[1].value=255; - } - else { - analog.alarms[1].value = round((alarm2value-((calib*ratio)/255))/ratio*255); - } - update(); - emit modified(); -} - -TelemetryAnalog::~TelemetryAnalog() -{ - delete ui; -} - -/******************************************************/ - TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetryCustomScreen), @@ -324,17 +35,17 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, { ui->setupUi(this); - for (int l=0; l<4; l++) { - for (int c=0; cgetCapability(TelemetryCustomScreensFieldsPerLine); c++) { + for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) { + for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) { fieldsCB[l][c] = new QComboBox(this); - fieldsCB[l][c]->setProperty("index", c + (l<<8)); + fieldsCB[l][c]->setProperty("index", c + (l << 8)); fieldsCB[l][c]->setModel(srcModel); ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1); connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int))); } } - for (int l=0; l<4; l++) { + for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) { barsCB[l] = new QComboBox(this); barsCB[l]->setProperty("index", l); barsCB[l]->setModel(srcModel); @@ -377,8 +88,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, disableMouseScrolling(); lock = true; - if (IS_ARM(firmware->getBoard())) - ui->screenType->addItem(tr("None"), TELEMETRY_SCREEN_NONE); + ui->screenType->addItem(tr("None"), TELEMETRY_SCREEN_NONE); ui->screenType->addItem(tr("Numbers"), TELEMETRY_SCREEN_NUMBERS); ui->screenType->addItem(tr("Bars"), TELEMETRY_SCREEN_BARS); if (IS_TARANIS(firmware->getBoard())) @@ -409,18 +119,18 @@ void TelemetryCustomScreen::update() ui->screenNums->setVisible(screen.type == TELEMETRY_SCREEN_NUMBERS); ui->screenBars->setVisible(screen.type == TELEMETRY_SCREEN_BARS); - for (int l=0; l<4; l++) { - for (int c=0; cgetCapability(TelemetryCustomScreensFieldsPerLine); c++) { + for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) { + for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) { fieldsCB[l][c]->setCurrentIndex(fieldsCB[l][c]->findData(screen.body.lines[l].source[c].toValue())); } } - for (int l=0; l<4; l++) { + for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) { barsCB[l]->setCurrentIndex(barsCB[l]->findData(screen.body.bars[l].source.toValue())); } if (screen.type == TELEMETRY_SCREEN_BARS) { - for (int i=0; i<4; i++) { + for (int i = 0; i < firmware->getCapability(TelemetryCustomScreensBars); i++) { updateBar(i); } } @@ -439,14 +149,8 @@ void TelemetryCustomScreen::updateBar(int line) if (source.type != SOURCE_TYPE_NONE) { RawSourceRange range = source.getRange(model, generalSettings); - if (!IS_ARM(getCurrentBoard())) { - int max = round((range.max - range.min) / range.step); - if (int(255-screen.body.bars[line].barMax) > max) { - screen.body.bars[line].barMax = 255 - max; - } - } float minVal = range.getValue(screen.body.bars[line].barMin); - float maxVal = IS_ARM(getCurrentBoard()) ? screen.body.bars[line].barMax : 255 - screen.body.bars[line].barMax; + float maxVal = screen.body.bars[line].barMax; maxVal = range.getValue(maxVal); if (source.isTimeBased()) { @@ -552,10 +256,7 @@ void TelemetryCustomScreen::barMinChanged(double value) { if (!lock) { int line = sender()->property("index").toInt(); - if (IS_ARM(getCurrentBoard())) - screen.body.bars[line].barMin = round(value / minSB[line]->singleStep()); - else - screen.body.bars[line].barMin = round((value-minSB[line]->minimum()) / minSB[line]->singleStep()); + screen.body.bars[line].barMin = round(value / minSB[line]->singleStep()); // TODO set min (maxSB) emit modified(); } @@ -565,10 +266,7 @@ void TelemetryCustomScreen::barMaxChanged(double value) { if (!lock) { int line = sender()->property("index").toInt(); - if (IS_ARM(getCurrentBoard())) - screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep()); - else - screen.body.bars[line].barMax = 255 - round((value-minSB[line]->minimum()) / maxSB[line]->singleStep()); + screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep()); // TODO set max (minSB) emit modified(); } @@ -583,10 +281,7 @@ void TelemetryCustomScreen::barTimeChanged() if (!te) return; - if (IS_ARM(getCurrentBoard())) - valRef = round(te->timeInSeconds() / te->singleStep()); - else - valRef = round((te->timeInSeconds() - te->minimumTime()) / te->singleStep()); + valRef = round(te->timeInSeconds() / te->singleStep()); emit modified(); } @@ -594,13 +289,14 @@ void TelemetryCustomScreen::barTimeChanged() /******************************************************/ -TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetrySensor), sensor(sensor), lock(false), sensorIndex(sensorIndex), - selectedIndex(0) + selectedIndex(0), + sensorCapability(sensorCapability) { ui->setupUi(this); ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1)); @@ -628,7 +324,7 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ui->ampsSensor->setField(sensor.amps, this); ui->cellsSensor->setField(sensor.source, this); ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST); - for (int i = 1; i <= 6; i++) + for (int i = SensorData::TELEM_CELL_INDEX_LOWEST + 1; i < SensorData::TELEM_CELL_INDEX_HIGHEST; i++) ui->cellsIndex->addItem(tr("Cell %1").arg(i), i); ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST); ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA); @@ -777,8 +473,8 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model { cb->clear(); if (negative) { - for (int i=-CPN_MAX_SENSORS; i<0; ++i) { - const SensorData& sensor = model->sensorData[-i-1]; + for (int i = -CPN_MAX_SENSORS; i < 0; ++i) { + const SensorData& sensor = model->sensorData[-i - 1]; if (sensor.isAvailable()) { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); @@ -788,7 +484,7 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model } } cb->addItem("---", 0); - for (unsigned i=1; i<=CPN_MAX_SENSORS; ++i) { + for (unsigned i = 1; i <= CPN_MAX_SENSORS; ++i) { const SensorData& sensor = model->sensorData[i-1]; if (sensor.isAvailable()) { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) @@ -874,6 +570,11 @@ void TelemetrySensorPanel::on_customContextMenuRequested(QPoint pos) contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData()); contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear())); contextMenu.addSeparator(); + contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed()); + contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete())); + contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed()); + contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed()); + contextMenu.addSeparator(); contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll())); contextMenu.exec(globalPos); @@ -891,6 +592,21 @@ bool TelemetrySensorPanel::hasClipboardData(QByteArray * data) const return false; } +bool TelemetrySensorPanel::insertAllowed() const +{ + return ((selectedIndex < sensorCapability - 1) && (model->sensorData[sensorCapability - 1].isEmpty())); +} + +bool TelemetrySensorPanel::moveDownAllowed() const +{ + return selectedIndex < sensorCapability - 1; +} + +bool TelemetrySensorPanel::moveUpAllowed() const +{ + return selectedIndex > 0; +} + void TelemetrySensorPanel::cmCopy() { QByteArray data; @@ -902,8 +618,11 @@ void TelemetrySensorPanel::cmCopy() void TelemetrySensorPanel::cmCut() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + cmCopy(); - cmClear(); + cmClear(false); } void TelemetrySensorPanel::cmPaste() @@ -916,12 +635,15 @@ void TelemetrySensorPanel::cmPaste() } } -void TelemetrySensorPanel::cmClear() +void TelemetrySensorPanel::cmClear(bool prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; + if (prompt) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } sensor.clear(); + model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); emit dataModified(); emit modified(); } @@ -934,6 +656,26 @@ void TelemetrySensorPanel::cmClearAll() emit clearAllSensors(); } +void TelemetrySensorPanel::cmInsert() +{ + emit insertSensor(selectedIndex); +} + +void TelemetrySensorPanel::cmDelete() +{ + emit deleteSensor(selectedIndex); +} + +void TelemetrySensorPanel::cmMoveUp() +{ + emit moveUpSensor(selectedIndex); +} + +void TelemetrySensorPanel::cmMoveDown() +{ + emit moveDownSensor(selectedIndex); +} + /******************************************************/ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): @@ -942,33 +684,29 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin { ui->setupUi(this); + sensorCapability = firmware->getCapability(Sensors); + if (sensorCapability > CPN_MAX_SENSORS) // TODO should be role of getCapability + sensorCapability = CPN_MAX_SENSORS; + if (firmware->getCapability(NoTelemetryProtocol)) { model.frsky.usrProto = 1; } - if (IS_ARM(firmware->getBoard())) { - ui->varioSource->setField(model.frsky.varioSource, this); - ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this); - ui->A1GB->hide(); - ui->A2GB->hide(); - for (unsigned i= 0; i < CPN_MAX_SENSORS; ++i) { - TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, model, generalSettings, firmware); - ui->sensorsLayout->addWidget(panel); - sensorPanels[i] = panel; - connect(panel, SIGNAL(dataModified()), this, SLOT(update())); - connect(panel, SIGNAL(modified()), this, SLOT(onModified())); - connect(panel, SIGNAL(clearAllSensors()), this, SLOT(on_clearAllSensors())); - } - } - else { - ui->sensorsGB->hide(); - ui->altimetryGB->hide(); - analogs[0] = new TelemetryAnalog(this, model.frsky.channels[0], model, generalSettings, firmware); - ui->A1Layout->addWidget(analogs[0]); - connect(analogs[0], SIGNAL(modified()), this, SLOT(onAnalogModified())); - analogs[1] = new TelemetryAnalog(this, model.frsky.channels[1], model, generalSettings, firmware); - ui->A2Layout->addWidget(analogs[1]); - connect(analogs[1], SIGNAL(modified()), this, SLOT(onModified())); + ui->varioSource->setField(model.frsky.varioSource, this); + ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this); + ui->A1GB->hide(); + ui->A2GB->hide(); + for (int i = 0; i < sensorCapability; ++i) { + TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, firmware); + ui->sensorsLayout->addWidget(panel); + sensorPanels[i] = panel; + connect(panel, SIGNAL(dataModified()), this, SLOT(update())); + connect(panel, SIGNAL(modified()), this, SLOT(onModified())); + connect(panel, SIGNAL(clearAllSensors()), this, SLOT(on_clearAllSensors())); + connect(panel, SIGNAL(insertSensor(int)), this, SLOT(on_insertSensor(int))); + connect(panel, SIGNAL(deleteSensor(int)), this, SLOT(on_deleteSensor(int))); + connect(panel, SIGNAL(moveUpSensor(int)), this, SLOT(on_moveUpSensor(int))); + connect(panel, SIGNAL(moveDownSensor(int)), this, SLOT(on_moveDownSensor(int))); } if (IS_TARANIS_X9(firmware->getBoard())) { @@ -984,7 +722,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel); - ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1)); + ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i + 1)); telemetryCustomScreens[i] = tab; connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified); connect(this, &TelemetryPanel::updated, tab, &TelemetryCustomScreen::update); @@ -1017,10 +755,8 @@ void TelemetryPanel::update() populateTelemetrySourcesComboBox(ui->varioSource, model, false); } - if (IS_ARM(firmware->getBoard())) { - for (unsigned i=0; iupdate(); - } + for (int i = 0; i < sensorCapability; ++i) { + sensorPanels[i]->update(); } emit updated(); @@ -1032,52 +768,29 @@ void TelemetryPanel::setup() lock = true; - if (IS_ARM(firmware->getBoard())) { - ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0); - ui->telemetryProtocol->addItem(tr("FrSky D"), 1); - if (IS_9XRPRO(firmware->getBoard()) || - (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) { - ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2); - } - ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol); - ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this); - ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled); - } - else { - ui->telemetryProtocolLabel->hide(); - ui->telemetryProtocol->hide(); - ui->ignoreSensorIds->hide(); - ui->disableTelemetryAlarms->hide(); + ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0); + ui->telemetryProtocol->addItem(tr("FrSky D"), 1); + if (IS_9XRPRO(firmware->getBoard()) || + (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) { + ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2); } + ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol); + ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this); + ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled); ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning); ui->rssiAlarmCriticalSB->setValue(model->rssiAlarms.critical); - if (!IS_ARM(firmware->getBoard())) { - ui->rssiSourceLabel->hide(); - ui->rssiSourceCB->hide(); - ui->rssiAlarmWarningCB->setCurrentIndex(model->rssiAlarms.level[0]); - ui->rssiAlarmCriticalCB->setCurrentIndex(model->rssiAlarms.level[1]); - } - else { - ui->rssiSourceLabel->show(); - ui->rssiSourceLabel->setText(tr("Source")); - ui->rssiSourceCB->setField(model->rssiSource, this); - ui->rssiSourceCB->show(); - populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); - ui->rssiAlarmWarningCB->hide(); - ui->rssiAlarmCriticalCB->hide(); - ui->rssiAlarmWarningLabel->setText(tr("Low Alarm")); - ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm")); - } + ui->rssiSourceLabel->show(); + ui->rssiSourceLabel->setText(tr("Source")); + ui->rssiSourceCB->setField(model->rssiSource, this); + ui->rssiSourceCB->show(); + populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); - /*if (IS_ARM(firmware->getBoard())) { - for (int i=0; i, model, generalSettings, firmware); - ui->sensorsLayout->addWidget(panel); - sensorPanels[i] = panel; - } - }*/ + ui->rssiAlarmWarningCB->hide(); + ui->rssiAlarmCriticalCB->hide(); + ui->rssiAlarmWarningLabel->setText(tr("Low Alarm")); + ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm")); int varioCap = firmware->getCapability(HasVario); if (!varioCap) { @@ -1100,16 +813,16 @@ void TelemetryPanel::setup() ui->VarioLabel_1->hide(); ui->VarioLabel_2->hide(); } - ui->varioLimitMin_DSB->setValue(model->frsky.varioMin-10); - ui->varioLimitMax_DSB->setValue(model->frsky.varioMax+10); - ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax/10.0)+0.5); - ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin/10.0)-0.5); + ui->varioLimitMin_DSB->setValue(model->frsky.varioMin - 10); + ui->varioLimitMax_DSB->setValue(model->frsky.varioMax + 10); + ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax / 10.0) + 0.5); + ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin / 10.0) - 0.5); } ui->altimetryGB->setVisible(firmware->getCapability(HasVario)), ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol)); - if (firmware->getCapability(Telemetry) & TM_HASWSHH) { + if (firmware->getCapability(Telemetry)) { ui->frskyProtoCB->addItem(tr("Winged Shadow How High")); } else { @@ -1117,38 +830,6 @@ void TelemetryPanel::setup() } ui->variousGB->hide(); - if (!IS_ARM(firmware->getBoard())) { - if (!(firmware->getCapability(HasFasOffset)) && !(firmware_id.contains("fasoffset"))) { - ui->fasOffset_label->hide(); - ui->fasOffset_DSB->hide(); - } - else { - ui->fasOffset_DSB->setValue(model->frsky.fasOffset/10.0); - ui->variousGB->show(); - } - - if (!(firmware->getCapability(HasMahPersistent))) { - ui->mahCount_label->hide(); - ui->mahCount_SB->hide(); - ui->mahCount_ChkB->hide(); - } - else { - if (model->frsky.mAhPersistent) { - ui->mahCount_ChkB->setChecked(true); - ui->mahCount_SB->setValue(model->frsky.storedMah); - } - else { - ui->mahCount_SB->setDisabled(true); - } - ui->variousGB->show(); - } - - ui->frskyProtoCB->setCurrentIndex(model->frsky.usrProto); - ui->bladesCount->setValue(model->frsky.blades); - populateVarioSource(); - populateVoltsSource(); - populateCurrentSource(); - } lock = false; } @@ -1170,10 +851,8 @@ void TelemetryPanel::populateVoltsSource() cb->setField(model->frsky.voltsSource, this); cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1); cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2); - if (IS_ARM(firmware->getBoard())) { - cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3); - cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4); - } + cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3); + cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4); cb->addItem(tr("FAS"), TELEMETRY_VOLTS_SOURCE_FAS); cb->addItem(tr("Cells"), TELEMETRY_VOLTS_SOURCE_CELLS); } @@ -1185,10 +864,8 @@ void TelemetryPanel::populateCurrentSource() cb->addItem(tr("---"), TELEMETRY_CURRENT_SOURCE_NONE); cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1); cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2); - if (IS_ARM(firmware->getBoard())) { - cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3); - cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4); - } + cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3); + cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4); cb->addItem(tr("FAS"), TELEMETRY_CURRENT_SOURCE_FAS); } @@ -1217,24 +894,12 @@ void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index) { if (!lock) { model->frsky.usrProto = index; - for (int i=0; igetCapability(TelemetryCustomScreens); i++) + for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) telemetryCustomScreens[i]->update(); emit modified(); } } -void TelemetryPanel::on_rssiAlarmWarningCB_currentIndexChanged(int index) -{ - model->rssiAlarms.level[0] = index; - emit modified(); -} - -void TelemetryPanel::on_rssiAlarmCriticalCB_currentIndexChanged(int index) -{ - model->rssiAlarms.level[1] = index; - emit modified(); -} - void TelemetryPanel::on_rssiAlarmWarningSB_editingFinished() { model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value(); @@ -1249,23 +914,23 @@ void TelemetryPanel::on_rssiAlarmCriticalSB_editingFinished() void TelemetryPanel::on_varioLimitMin_DSB_editingFinished() { - model->frsky.varioMin = round(ui->varioLimitMin_DSB->value()+10); + model->frsky.varioMin = round(ui->varioLimitMin_DSB->value() + 10); emit modified(); } void TelemetryPanel::on_varioLimitMax_DSB_editingFinished() { - model->frsky.varioMax = round(ui->varioLimitMax_DSB->value()-10); + model->frsky.varioMax = round(ui->varioLimitMax_DSB->value() - 10); emit modified(); } void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() { if (!lock) { - if (ui->varioLimitCenterMin_DSB->value()>ui->varioLimitCenterMax_DSB->value()) { + if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) { ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value()); } - model->frsky.varioCenterMin = round((ui->varioLimitCenterMin_DSB->value()+0.5)*10); + model->frsky.varioCenterMin = round((ui->varioLimitCenterMin_DSB->value() + 0.5) * 10); emit modified(); } } @@ -1273,10 +938,10 @@ void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished() { if (!lock) { - if (ui->varioLimitCenterMin_DSB->value()>ui->varioLimitCenterMax_DSB->value()) { + if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) { ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value()); } - model->frsky.varioCenterMax = round((ui->varioLimitCenterMax_DSB->value()-0.5)*10); + model->frsky.varioCenterMax = round((ui->varioLimitCenterMax_DSB->value() - 0.5) * 10); emit modified(); } } @@ -1304,8 +969,56 @@ void TelemetryPanel::on_clearAllSensors() { for (int i = 0; i < CPN_MAX_SENSORS; i++) { model->sensorData[i].clear(); + model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, i); } update(); emit modified(); } + +void TelemetryPanel::on_insertSensor(int selectedIndex) +{ + memmove(&model->sensorData[selectedIndex + 1], &model->sensorData[selectedIndex], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData)); + model->sensorData[selectedIndex].clear(); + model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); + + update(); + emit modified(); +} + +void TelemetryPanel::on_deleteSensor(int selectedIndex) +{ + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + + memmove(&model->sensorData[selectedIndex], &model->sensorData[selectedIndex + 1], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData)); + model->sensorData[CPN_MAX_SENSORS - 1].clear(); + model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1); + + update(); + emit modified(); +} + +void TelemetryPanel::on_moveUpSensor(int selectedIndex) +{ + swapData(selectedIndex, selectedIndex - 1); +} + +void TelemetryPanel::on_moveDownSensor(int selectedIndex) +{ + swapData(selectedIndex, selectedIndex + 1); +} + +void TelemetryPanel::swapData(int idx1, int idx2) +{ + if ((idx1 != idx2) && (!model->sensorData[idx1].isEmpty() || !model->sensorData[idx2].isEmpty())) { + SensorData sdtmp = model->sensorData[idx2]; + SensorData *sd1 = &model->sensorData[idx1]; + SensorData *sd2 = &model->sensorData[idx2]; + memcpy(sd2, sd1, sizeof(SensorData)); + memcpy(sd1, &sdtmp, sizeof(SensorData)); + model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); + update(); + emit modified(); + } +} diff --git a/companion/src/modeledit/telemetry.h b/companion/src/modeledit/telemetry.h index 39f3a42ad..cddade217 100644 --- a/companion/src/modeledit/telemetry.h +++ b/companion/src/modeledit/telemetry.h @@ -31,45 +31,11 @@ class RawSourceFilterItemModel; class TimerEdit; namespace Ui { - class TelemetryAnalog; class TelemetryCustomScreen; class TelemetrySensor; class Telemetry; } -class TelemetryAnalog: public ModelPanel -{ - Q_OBJECT - - friend class TelemetryPanel; - - public: - TelemetryAnalog(QWidget *parent, FrSkyChannelData & analog, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); - virtual ~TelemetryAnalog(); - - signals: - void modified(); - - private slots: - void on_UnitCB_currentIndexChanged(int index); - void on_RatioSB_editingFinished(); - void on_RatioSB_valueChanged(); - void on_CalibSB_editingFinished(); - void on_alarm1LevelCB_currentIndexChanged(int index); - void on_alarm1GreaterCB_currentIndexChanged(int index); - void on_alarm1ValueSB_editingFinished(); - void on_alarm2LevelCB_currentIndexChanged(int index); - void on_alarm2GreaterCB_currentIndexChanged(int index); - void on_alarm2ValueSB_editingFinished(); - - private: - Ui::TelemetryAnalog *ui; - FrSkyChannelData & analog; - bool lock; - - void update(); -}; - class TelemetryCustomScreen: public ModelPanel { Q_OBJECT @@ -105,13 +71,18 @@ class TelemetrySensorPanel: public ModelPanel Q_OBJECT public: - TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); ~TelemetrySensorPanel(); void update(); signals: void dataModified(); void clearAllSensors(); + void insertSensor(int index); + void deleteSensor(int index); + void moveUpSensor(int index); + void moveDownSensor(int index); + protected slots: void on_name_editingFinished(); @@ -124,8 +95,12 @@ class TelemetrySensorPanel: public ModelPanel void cmCopy(); void cmCut(); void cmPaste(); - void cmClear(); + void cmClear(bool prompt = true); void cmClearAll(); + void cmInsert(); + void cmDelete(); + void cmMoveUp(); + void cmMoveDown(); protected: void updateSourcesComboBox(AutoComboBox * cb, bool negative); @@ -136,6 +111,10 @@ class TelemetrySensorPanel: public ModelPanel bool lock = false; int sensorIndex = 0; int selectedIndex = 0; + int sensorCapability; + bool insertAllowed() const; + bool moveDownAllowed() const; + bool moveUpAllowed() const; }; class TelemetryPanel : public ModelPanel @@ -155,8 +134,6 @@ class TelemetryPanel : public ModelPanel void onModified(); void on_frskyProtoCB_currentIndexChanged(int index); void on_bladesCount_editingFinished(); - void on_rssiAlarmWarningCB_currentIndexChanged(int index); - void on_rssiAlarmCriticalCB_currentIndexChanged(int index); void on_rssiAlarmWarningSB_editingFinished(); void on_rssiAlarmCriticalSB_editingFinished(); void on_varioLimitMin_DSB_editingFinished(); @@ -167,18 +144,23 @@ class TelemetryPanel : public ModelPanel void on_mahCount_SB_editingFinished(); void on_mahCount_ChkB_toggled(bool checked); void on_clearAllSensors(); + void on_insertSensor(int index); + void on_deleteSensor(int index); + void on_moveUpSensor(int index); + void on_moveDownSensor(int index); private: Ui::Telemetry *ui; - TelemetryAnalog * analogs[4]; TelemetryCustomScreen * telemetryCustomScreens[4]; TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS]; + int sensorCapability; void setup(); void telBarUpdate(); void populateVoltsSource(); void populateCurrentSource(); void populateVarioSource(); + void swapData(int idx1, int idx2); }; #endif // _TELEMETRY_H_ diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp index dde8517e0..3dc945f5d 100644 --- a/companion/src/modelprinter.cpp +++ b/companion/src/modelprinter.cpp @@ -212,7 +212,7 @@ QString ModelPrinter::printModule(int idx) str << printLabelValue(tr("Delay"), QString("%1us").arg(module.ppm.delay)); } else { - if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_SBUS)) { + if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_GHOST || module.protocol == PULSES_SBUS)) { str << printLabelValue(tr("Receiver"), QString::number(module.modelId)); } if (module.protocol == PULSES_MULTIMODULE) { @@ -224,6 +224,11 @@ QString ModelPrinter::printModule(int idx) str << printLabelValue(tr("Sub Type"), module.subTypeToString()); str << printLabelValue(tr("RF Output Power"), module.powerValueToString(firmware)); } + if (module.protocol == PULSES_AFHDS3) { + str << printLabelValue(tr("Output Type"), module.subTypeToString()); + str << printLabelValue(tr("RF Output Power"), module.powerValueToString(firmware)); + str << printLabelValue(tr("RX Output Frequency"), QString("%1Hz").arg(module.afhds3.rxFreq)); + } } } result = str.join(" "); @@ -968,8 +973,7 @@ QString ModelPrinter::printSettingsTrim() { QStringList str; str << printLabelValue(tr("Step"), printTrimIncrementMode()); - if (IS_ARM(firmware->getBoard())) - str << printLabelValue(tr("Display"), printTrimsDisplayMode()); + str << printLabelValue(tr("Display"), printTrimsDisplayMode()); str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO)); return str.join(" "); } diff --git a/companion/src/multimodelprinter.cpp b/companion/src/multimodelprinter.cpp index f9d039d69..4da889cb1 100644 --- a/companion/src/multimodelprinter.cpp +++ b/companion/src/multimodelprinter.cpp @@ -292,7 +292,7 @@ QString MultiModelPrinter::print(QTextDocument * document) if (firmware->getCapability(GlobalFunctions)) str.append(printGlobalFunctions()); str.append(printSpecialFunctions()); - if (firmware->getCapability(Telemetry) & TM_HASTELEMETRY) { + if (firmware->getCapability(Telemetry)) { str.append(printTelemetry()); str.append(printSensors()); if (firmware->getCapability(TelemetryCustomScreens)) { @@ -310,7 +310,9 @@ QString MultiModelPrinter::printSetup() MultiColumns columns(modelPrinterMap.size()); columns.appendSectionTableStart(); ROWLABELCOMPARECELL(tr("Name"), 20, model->name, 80); - ROWLABELCOMPARECELL(tr("EEprom Size"), 0, modelPrinter->printEEpromSize(), 0); + if (!IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) { + ROWLABELCOMPARECELL(tr("EEprom Size"), 0, modelPrinter->printEEpromSize(), 0); + } if (firmware->getCapability(ModelImage)) { ROWLABELCOMPARECELL(tr("Model Image"), 0, model->bitmap, 0); } @@ -751,32 +753,19 @@ QString MultiModelPrinter::printTelemetry() MultiColumns columns(modelPrinterMap.size()); columns.appendSectionTableStart(); - // Analogs on non ARM boards - if (!IS_ARM(firmware->getBoard())) { - columns.appendRowHeader(QStringList() << tr("Analogs") << tr("Unit") << tr("Scale") << tr("Offset")); - for (int i=0; i<2; i++) { - columns.appendRowStart(QString("A%1").arg(i+1), 20); - COMPARECELLWIDTH(FrSkyChannelData::unitString(model->frsky.channels[i].type), 20); - COMPARECELLWIDTH(QString::number((model->frsky.channels[i].ratio / (model->frsky.channels[i].type==0 ? 10.0 : 1)), 10, (model->frsky.channels[i].type==0 ? 1 : 0)), 20); - COMPARECELLWIDTH(QString::number((model->frsky.channels[i].offset*(model->frsky.channels[i].ratio / (model->frsky.channels[i].type==0 ?10.0 : 1)))/255, 10, (model->frsky.channels[i].type==0 ? 1 : 0)), 40); - columns.appendRowEnd(); - } - } - else { - // Protocol - columns.appendRowStart(tr("Protocol"), 20); - COMPARECELL(modelPrinter->printTelemetryProtocol(model->telemetryProtocol)); - columns.appendRowEnd(); - } + // Protocol + columns.appendRowStart(tr("Protocol"), 20); + COMPARECELL(modelPrinter->printTelemetryProtocol(model->telemetryProtocol)); + columns.appendRowEnd(); // RSSI alarms { columns.appendRowStart(tr("RSSI Alarms"), 20); columns.appendCellStart(80); - COMPARESTRING("", (IS_ARM(getCurrentBoard()) ? tr("Low") : FrSkyAlarmData::alarmLevelName(model->rssiAlarms.level[0])), false); + COMPARESTRING("", tr("Low"), false); columns.append(": "); COMPARESTRING("", QString("< %1").arg(QString::number(model->rssiAlarms.warning, 10)), true); - COMPARESTRING("", (IS_ARM(getCurrentBoard()) ? tr("Critical") : FrSkyAlarmData::alarmLevelName(model->rssiAlarms.level[1])), false); + COMPARESTRING("", tr("Critical"), false); columns.append(": "); COMPARESTRING("", QString("< %1").arg(QString::number(model->rssiAlarms.critical, 10)), true); COMPARESTRING(tr("Telemetry audio"), modelPrinter->printRssiAlarmsDisabled(model->rssiAlarms.disabled), false); @@ -818,39 +807,9 @@ QString MultiModelPrinter::printTelemetry() columns.appendRowEnd(); } - if (IS_ARM(firmware->getBoard())) { - ROWLABELCOMPARECELL("Multi sensors", 0, modelPrinter->printIgnoreSensorIds(!model->frsky.ignoreSensorIds), 0); - } + ROWLABELCOMPARECELL("Multi sensors", 0, modelPrinter->printIgnoreSensorIds(!model->frsky.ignoreSensorIds), 0); // Various - if (!IS_ARM(firmware->getBoard())) { - columns.appendRowHeader(QStringList() << tr("Various")); - if (!firmware->getCapability(NoTelemetryProtocol)) { - columns.appendRowStart("", 20); - LABELCOMPARECELL(tr("Serial protocol"), modelPrinter->printTelemetrySource(model->frsky.voltsSource), 80); - columns.appendRowEnd(); - } - columns.appendRowStart("", 20); - columns.appendCellStart(80); - QString firmware_id = g.profile[g.id()].fwType(); - if (firmware->getCapability(HasFasOffset) && firmware_id.contains("fasoffset")) { - COMPARESTRING(tr("FAS offset"), QString("%1 A").arg(model->frsky.fasOffset/10.0), true); - } - if (firmware->getCapability(HasMahPersistent)) { - COMPARESTRING(tr("mAh count"), QString("%1 mAh").arg(model->frsky.storedMah), true); - COMPARESTRING(tr("Persistent mAh"), modelPrinter->printMahPersistent(model->frsky.mAhPersistent), false); - } - columns.appendRowEnd(); - columns.appendRowStart("", 20); - columns.appendCellStart(80); - COMPARESTRING(tr("Volts source"), modelPrinter->printVoltsSource(model->frsky.voltsSource), true); - COMPARESTRING(tr("Current source"), modelPrinter->printCurrentSource(model->frsky.currentSource), false); - columns.appendCellEnd(); - columns.appendRowEnd(); - columns.appendRowStart("", 20); - LABELCOMPARECELL(tr("Blades"), model->frsky.blades, 80); - columns.appendRowEnd(); - } columns.appendTableEnd(); str.append(columns.print()); return str; diff --git a/companion/src/profilechooser.cpp b/companion/src/profilechooser.cpp index 17a9570e5..a8942652e 100644 --- a/companion/src/profilechooser.cpp +++ b/companion/src/profilechooser.cpp @@ -28,6 +28,7 @@ ProfileChooserDialog::ProfileChooserDialog(QWidget * parent): { ui->setupUi(this); setWindowIcon(QIcon(":/icon.png")); + setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); QComboBox *prof = ui->cboProfiles; prof->clear(); diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp index fbc03186f..0ad24fe6c 100644 --- a/companion/src/radiointerface.cpp +++ b/companion/src/radiointerface.cpp @@ -36,43 +36,8 @@ QString getRadioInterfaceCmd() if (IS_STM32(board)) { return bcd.getDFU(); } - else if (IS_SKY9X(board)) { + else return bcd.getSAMBA(); - } - else { - return bcd.getAVRDUDE(); - } -} - -QStringList getAvrdudeArgs(const QString & cmd, const QString & filename) -{ - QStringList args; - burnConfigDialog bcd; - QString programmer = bcd.getProgrammer(); - QString mcu = bcd.getMCU(); - Board::Type board = getCurrentBoard(); - - args << "-c" << programmer << "-p"; - if (IS_2560(board)) - args << "m2560"; - else if (board == Board::BOARD_9X_M128) - args << "m128"; - else - args << mcu; - - args << bcd.getAvrdudeArgs(); - - QString fullcmd = cmd + filename; - if (QFileInfo(filename).suffix().toUpper() == "HEX") - fullcmd += ":i"; - else if (QFileInfo(filename).suffix().toUpper()=="BIN") - fullcmd += ":r"; - else - fullcmd += ":a"; - - args << "-U" << fullcmd; - - return args; } QStringList getDfuArgs(const QString & cmd, const QString & filename) @@ -119,11 +84,8 @@ QStringList getReadEEpromCmd(const QString & filename) if (IS_STM32(eepromInterface->getBoard())) { // impossible } - else if (IS_SKY9X(eepromInterface->getBoard())) { - result = getSambaArgs(QString("SERIALFLASH::Init 0\n") + "receive_file {SerialFlash AT25} \"" + filename + "\" 0x0 0x80000 0\n"); - } else { - result = getAvrdudeArgs("eeprom:r:", filename); + result = getSambaArgs(QString("SERIALFLASH::Init 0\n") + "receive_file {SerialFlash AT25} \"" + filename + "\" 0x0 0x80000 0\n"); } return result; } @@ -135,11 +97,8 @@ QStringList getWriteEEpromCmd(const QString & filename) // impossible return QStringList(); } - else if (IS_SKY9X(board)) { - return getSambaArgs(QString("SERIALFLASH::Init 0\n") + "send_file {SerialFlash AT25} \"" + filename + "\" 0x0 0\n"); - } else { - return getAvrdudeArgs("eeprom:w:", filename); + return getSambaArgs(QString("SERIALFLASH::Init 0\n") + "send_file {SerialFlash AT25} \"" + filename + "\" 0x0 0\n"); } } @@ -152,11 +111,8 @@ QStringList getWriteFirmwareArgs(const QString & filename) else if (board == Board::BOARD_SKY9X) { return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n"); } - else if (board == Board::BOARD_9XRPRO || board == Board::BOARD_AR9X) { - return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n"); - } else { - return getAvrdudeArgs("flash:w:", filename); + return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n"); } } @@ -169,87 +125,8 @@ QStringList getReadFirmwareArgs(const QString & filename) else if (board == Board::BOARD_SKY9X) { return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x40000 0\n"); } - else if (board == Board::BOARD_9XRPRO) { - return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x80000 0\n"); - } else { - return getAvrdudeArgs("flash:r:", filename); - } -} - -void readAvrdudeFuses(ProgressWidget * progress) -{ - burnConfigDialog bcd; - QStringList args; - args << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << bcd.getAvrdudeArgs() << "-U" << "lfuse:r:-:i" << "-U" << "hfuse:r:-:i" << "-U" << "efuse:r:-:i"; - FlashProcess flashProcess(bcd.getAVRDUDE(), args, progress); - flashProcess.run(); -} - -void resetAvrdudeFuses(bool eepromProtect, ProgressWidget * progress) -{ - //fuses - //avrdude -c usbasp -p m64 -U lfuse:w:<0x0E>:m - //avrdude -c usbasp -p m64 -U hfuse:w:<0x89>:m 0x81 for eeprom protection - //avrdude -c usbasp -p m64 -U efuse:w:<0xFF>:m - - burnConfigDialog bcd; - QMessageBox::StandardButton ret = QMessageBox::No; - ret = QMessageBox::warning(NULL, CPN_STR_APP_NAME, - QCoreApplication::translate("RadioInterface", - "WARNING!" \ - "
This will reset the fuses of %1 to the factory settings.
" - "Writing fuses can mess up your radio.
Do this only if you are sure they are wrong!
" - "Are you sure you want to continue?").arg(bcd.getMCU()), - QMessageBox::Yes | QMessageBox::No); - if (ret == QMessageBox::Yes) { - QStringList args = bcd.getAvrdudeArgs(); - QStringList str; - if (bcd.getMCU() == "m2560") { - args << "-B8"; - QString erStr = eepromProtect ? "hfuse:w:0x51:m" : "hfuse:w:0x59:m"; - str << "-U" << "lfuse:w:0xD7:m" << "-U" << erStr << "-U" << "efuse:w:0xFC:m"; - //use hfuse = 0x81 to prevent eeprom being erased with every flashing - } - else { - QString lfuses; - QString tempFile = generateProcessUniqueTempFileName("ftemp.bin"); - QStringList argread; - argread << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << args <<"-U" << "lfuse:r:"+tempFile+":r"; - FlashProcess flashProcess(bcd.getAVRDUDE(), argread, progress); - flashProcess.run(); - QFile file(tempFile); - if (file.exists() && file.size()==1) { - file.open(QIODevice::ReadOnly); - char bin_flash[1]; - file.read(bin_flash, 1); - if (bin_flash[0]==0x0E) { - lfuses = "lfuse:w:0x0E:m"; - } - else { - lfuses = "lfuse:w:0x3F:m"; - } - file.close(); - qunlink(tempFile); - } - else { - lfuses = "lfuse:w:0x3F:m"; - } - - QString erStr = eepromProtect ? "hfuse:w:0xC1:m" : "hfuse:w:0xC9:m"; - str << "-U" << lfuses << "-U" << erStr << "-U" << "efuse:w:0xFF:m"; - //use hfuse = 0x81 to prevent eeprom being erased with every flashing - } - - QStringList arguments; - if (bcd.getMCU() == "m2560") { - arguments << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << args << "-u" << str; - } - else { - arguments << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << args << "-B" << "100" << "-u" << str; - } - FlashProcess flashProcess(bcd.getAVRDUDE(), arguments, progress); - flashProcess.run(); + return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x80000 0\n"); } } @@ -264,13 +141,11 @@ bool readFirmware(const QString & filename, ProgressWidget * progress) return false; } - if (IS_ARM(getCurrentBoard())) { - QString path = findMassstoragePath("FIRMWARE.BIN"); - if (!path.isEmpty()) { - qDebug() << "readFirmware: reading" << path << "into" << filename; - CopyProcess copyProcess(path, filename, progress); - result = copyProcess.run(); - } + QString path = findMassstoragePath("FIRMWARE.BIN"); + if (!path.isEmpty()) { + qDebug() << "readFirmware: reading" << path << "into" << filename; + CopyProcess copyProcess(path, filename, progress); + result = copyProcess.run(); } if (!result) { @@ -288,13 +163,11 @@ bool readFirmware(const QString & filename, ProgressWidget * progress) bool writeFirmware(const QString & filename, ProgressWidget * progress) { - if (IS_ARM(getCurrentBoard())) { - QString path = findMassstoragePath("FIRMWARE.BIN"); - if (!path.isEmpty()) { - qDebug() << "writeFirmware: writing" << path << "from" << filename; - CopyProcess copyProcess(filename, path, progress); - return copyProcess.run(); - } + QString path = findMassstoragePath("FIRMWARE.BIN"); + if (!path.isEmpty()) { + qDebug() << "writeFirmware: writing" << path << "from" << filename; + CopyProcess copyProcess(filename, path, progress); + return copyProcess.run(); } qDebug() << "writeFirmware: writing" << filename << "with" << getRadioInterfaceCmd() << getWriteFirmwareArgs(filename); @@ -339,26 +212,25 @@ bool readEeprom(const QString & filename, ProgressWidget * progress) } } else { - if (IS_ARM(board)) { - QString path = findMassstoragePath("EEPROM.BIN"); - if (path.isEmpty()) { - // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :( - path = findMassstoragePath("TARANIS.BIN"); - } - if (path.isEmpty()) { - // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :( - path = findMassstoragePath("ERSKY9X.BIN"); - } - if (path.isEmpty()) { - RadioNotFoundDialog dialog(progress); - dialog.exec(); - return false; - } - CopyProcess copyProcess(path, filename, progress); - if (!copyProcess.run()) { - return false; - } + QString path = findMassstoragePath("EEPROM.BIN"); + if (path.isEmpty()) { + // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :( + path = findMassstoragePath("TARANIS.BIN"); } + if (path.isEmpty()) { + // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :( + path = findMassstoragePath("ERSKY9X.BIN"); + } + if (path.isEmpty()) { + RadioNotFoundDialog dialog(progress); + dialog.exec(); + return false; + } + CopyProcess copyProcess(path, filename, progress); + if (!copyProcess.run()) { + return false; + } + if (!IS_STM32(board)) { FlashProcess flashProcess(getRadioInterfaceCmd(), getReadEEpromCmd(filename), progress); @@ -375,20 +247,18 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress) { Board::Type board = getCurrentBoard(); - if (IS_ARM(board)) { - QString path = findMassstoragePath("EEPROM.BIN"); - if (path.isEmpty()) { - // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :( - path = findMassstoragePath("TARANIS.BIN"); - } - if (path.isEmpty()) { - // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :( - path = findMassstoragePath("ERSKY9X.BIN"); - } - if (!path.isEmpty()) { - CopyProcess copyProcess(filename, path, progress); - return copyProcess.run(); - } + QString path = findMassstoragePath("EEPROM.BIN"); + if (path.isEmpty()) { + // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :( + path = findMassstoragePath("TARANIS.BIN"); + } + if (path.isEmpty()) { + // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :( + path = findMassstoragePath("ERSKY9X.BIN"); + } + if (!path.isEmpty()) { + CopyProcess copyProcess(filename, path, progress); + return copyProcess.run(); } if (!IS_TARANIS(board)) { @@ -396,10 +266,8 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress) return flashProcess.run(); } - if (IS_ARM(board)) { - RadioNotFoundDialog dialog(progress); - dialog.exec(); - } + RadioNotFoundDialog dialog(progress); + dialog.exec(); return false; } diff --git a/companion/src/radiointerface.h b/companion/src/radiointerface.h index f896d96c5..37053fac5 100644 --- a/companion/src/radiointerface.h +++ b/companion/src/radiointerface.h @@ -30,13 +30,9 @@ QString getRadioInterfaceCmd(); QString findMassstoragePath(const QString &filename, bool onlyPath = false); -QStringList getAvrdudeArgs(const QString &cmd, const QString &filename); QStringList getSambaArgs(const QString &tcl); QStringList getDfuArgs(const QString &cmd, const QString &filename); -void readAvrdudeFuses(ProgressWidget *progress); -void resetAvrdudeFuses(bool eepromProtect, ProgressWidget *progress); - QStringList getReadEEpromCmd(const QString &filename); QStringList getWriteEEpromCmd(const QString &filename); QStringList getReadFirmwareArgs(const QString &filename); diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index 767933edf..462d5693f 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -14,6 +14,7 @@ set(simulation_SRCS simulateduiwidgetX12.cpp simulateduiwidgetJumperT12.cpp simulateduiwidgetJumperT16.cpp + simulateduiwidgetJumperT18.cpp simulateduiwidgetTX16S.cpp simulatorinterface.cpp simulatormainwindow.cpp @@ -39,6 +40,7 @@ set(simulation_UIS simulateduiwidgetX12.ui simulateduiwidgetJumperT12.ui simulateduiwidgetJumperT16.ui + simulateduiwidgetJumperT18.ui simulateduiwidgetTX16S.ui simulatormainwindow.ui simulatorstartupdialog.ui diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h index 75dd3ebfd..8419840c5 100644 --- a/companion/src/simulation/simulateduiwidget.h +++ b/companion/src/simulation/simulateduiwidget.h @@ -113,6 +113,7 @@ namespace Ui { class SimulatedUIWidgetX12; class SimulatedUIWidgetJumperT12; class SimulatedUIWidgetJumperT16; + class SimulatedUIWidgetJumperT18; class SimulatedUIWidgetTX16S; } @@ -252,6 +253,18 @@ class SimulatedUIWidgetJumperT16: public SimulatedUIWidget Ui::SimulatedUIWidgetJumperT16 * ui; }; +class SimulatedUIWidgetJumperT18: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidgetJumperT18(SimulatorInterface * simulator, QWidget * parent = nullptr); + virtual ~SimulatedUIWidgetJumperT18(); + + private: + Ui::SimulatedUIWidgetJumperT18 * ui; +}; + class SimulatedUIWidgetTX16S: public SimulatedUIWidget { Q_OBJECT diff --git a/companion/src/simulation/simulateduiwidgetJumperT18.cpp b/companion/src/simulation/simulateduiwidgetJumperT18.cpp new file mode 100644 index 000000000..1a66138ca --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperT18.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h + +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetJumperT18.h" + +SimulatedUIWidgetJumperT18::SimulatedUIWidgetJumperT18(SimulatorInterface *simulator, QWidget * parent): + SimulatedUIWidget(simulator, parent), + ui(new Ui::SimulatedUIWidgetJumperT18) +{ + RadioUiAction * act; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 90, 80, 35), "JumperT18/left_mdl.png", act)); + + act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS); + addRadioWidget(ui->leftbuttons->addArea(QRect(25, 5, 100, 40), "JumperT18/left_sys.png", act)); + + act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 180, 80, 35), "JumperT18/left_tele.png", act)); + + act = new RadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, + SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN); + addRadioWidget(ui->rightbuttons->addArea(QRect(20, 5, 100, 40), "JumperT18/right_rtn.png", act)); + + act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 140, 80, 35), "JumperT18/left.png", act)); + + m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT); + m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT); + connectScrollActions(); + + m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(25, 90, 70, 130), "JumperT18/right_ent.png", m_mouseMidClickAction)); + + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 245, 30, 30), "JumperT18/left_scrnsht.png", m_screenshotAction)); + + m_backlightColors << QColor(47, 123, 227); + + setLcd(ui->lcd); +} + +SimulatedUIWidgetJumperT18::~SimulatedUIWidgetJumperT18() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetJumperT18.ui b/companion/src/simulation/simulateduiwidgetJumperT18.ui new file mode 100644 index 000000000..1c14df404 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperT18.ui @@ -0,0 +1,197 @@ + + + SimulatedUIWidgetJumperT18 + + + + 0 + 0 + 825 + 292 + + + + + 0 + 0 + + + + + 825 + 292 + + + + + 825 + 292 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 131 + 289 + + + + + 131 + 289 + + + + background:url(:/images/simulator/JumperT18/right.png) + + + + + + + + 0 + 0 + + + + + 480 + 272 + + + + + 480 + 272 + + + + + 5 + + + + + + + + + 0 + 0 + + + + + 131 + 289 + + + + + 131 + 289 + + + + true + + + background:url(:/images/simulator/JumperT18/left.png); + + + + + + + + 0 + 0 + + + + + 480 + 10 + + + + + 480 + 10 + + + + + 5 + + + + background:url(:/images/simulator/JumperT18/top.png) + + + + + + + + 0 + 0 + + + + + 480 + 10 + + + + + 480 + 10 + + + + + 5 + false + + + + background:url(:/images/simulator/JumperT18/bottom.png) + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulatorstartupdialog.cpp b/companion/src/simulation/simulatorstartupdialog.cpp index 32d343321..b7faf0261 100644 --- a/companion/src/simulation/simulatorstartupdialog.cpp +++ b/companion/src/simulation/simulatorstartupdialog.cpp @@ -86,7 +86,7 @@ void SimulatorStartupDialog::changeEvent(QEvent *e) // FIXME : need a better way to check for this bool SimulatorStartupDialog::usesCategorizedStorage(const QString & name) { - return name.contains(QRegExp("(x12|x10|horus|16)", Qt::CaseInsensitive)); + return name.contains(QRegExp("(x12|x10|horus|16|18)", Qt::CaseInsensitive)); } bool SimulatorStartupDialog::usesCategorizedStorage() diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index d20e34cc7..f70813442 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -94,6 +94,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato case Board::BOARD_JUMPER_T16: radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this); break; + case Board::BOARD_JUMPER_T18: + radioUiWidget = new SimulatedUIWidgetJumperT18(simulator, this); + break; case Board::BOARD_RADIOMASTER_TX16S: radioUiWidget = new SimulatedUIWidgetTX16S(simulator, this); break; diff --git a/companion/src/storage/rlefile.cpp b/companion/src/storage/rlefile.cpp index fe297339f..4d38adac9 100644 --- a/companion/src/storage/rlefile.cpp +++ b/companion/src/storage/rlefile.cpp @@ -64,7 +64,7 @@ void RleFile::EeFsCreate(uint8_t *eeprom, int size, Board::Type board, unsigned } } } - else if (IS_TARANIS(board)) { + else { eeFsArm = (EeFsArm *)eeprom; eeFsVersion = 5; eeFsSize = 8+4*62; @@ -84,36 +84,6 @@ void RleFile::EeFsCreate(uint8_t *eeprom, int size, Board::Type board, unsigned eeFsArm->freeList = eeFsFirstBlock; // EeFsFlush(); } - else { - eeFs = (EeFs *)eeprom; - eeFsVersion = (IS_2560(board) || board==Board::BOARD_9X_M128) ? 5 : 4; - eeFsBlockSize = 16; - eeFsLinkSize = 1; - - if (eeFsVersion == 5) { - eeFsSize = 4+3*36; - eeFsFirstBlock = 1; - eeFsBlocksOffset = 112 - 16; - eeFsBlocksMax = 1 + (4096-112)/16; - } - else { - eeFsSize = 4+3*20; - eeFsFirstBlock = 4; - eeFsBlocksOffset = 0; - eeFsBlocksMax = 2048/16; - } - - memset(eeprom, 0, size); - eeFs->version = eeFsVersion; - eeFs->mySize = eeFsSize; - eeFs->freeList = 0; - eeFs->bs = eeFsBlockSize; - for (unsigned int i=eeFsFirstBlock; ifreeList = eeFsFirstBlock; - // EeFsFlush(); - } } PACK(struct EepromFileHeader @@ -146,7 +116,7 @@ bool RleFile::EeFsOpen(uint8_t *eeprom, int size, Board::Type board) searchFat(); return 1; } - else if (IS_TARANIS(board)) { + else { eeFsArm = (EeFsArm *)eeprom; eeFsVersion = eeFsArm->version; eeFsSize = 8+4*62; @@ -157,29 +127,6 @@ bool RleFile::EeFsOpen(uint8_t *eeprom, int size, Board::Type board) eeFsBlocksMax = 1 + (Boards::getEEpromSize(board)-eeFsSize) / eeFsBlockSize; return eeFsArm->mySize == eeFsSize; } - else { - eeFs = (EeFs *)eeprom; - eeFsVersion = eeFs->version; - eeFsBlockSize = 16; - eeFsLinkSize = 1; - if (eeFsVersion == 5) { - eeFsSize = 4+3*36; - eeFsFirstBlock = 1; - eeFsBlocksOffset = 112 - 16; - eeFsBlocksMax = 1 + (4096-112)/16; - } - else if (eeFsVersion == 4) { - eeFsSize = 4+3*20; - eeFsFirstBlock = 4; - eeFsBlocksOffset = 0; - eeFsBlocksMax = 2048/16; - } - else { - return 0; - } - - return eeFs->mySize == eeFsSize; - } } void RleFile::eeprom_read_block (void *pointer_ram, unsigned int pointer_eeprom, size_t size) @@ -206,25 +153,16 @@ void RleFile::EeFsWrite(unsigned int blk, unsigned int ofs, uint8_t val) unsigned int RleFile::EeFsGetLink(unsigned int blk) { - if (IS_ARM(board)) { - int16_t ret; - eeprom_read_block((uint8_t *)&ret, blk*eeFsBlockSize+eeFsBlocksOffset, eeFsLinkSize); - return ret; - } - else { - return EeFsRead(blk, 0); - } + int16_t ret; + eeprom_read_block((uint8_t *)&ret, blk*eeFsBlockSize+eeFsBlocksOffset, eeFsLinkSize); + return ret; } void RleFile::EeFsSetLink(unsigned int blk, unsigned int val) { - if (IS_ARM(board)) { - int16_t s_link = val; - eeprom_write_block((uint8_t *)&s_link, (blk*eeFsBlockSize)+eeFsBlocksOffset, eeFsLinkSize); - } - else { - EeFsWrite(blk, 0, val); - } + int16_t s_link = val; + eeprom_write_block((uint8_t *)&s_link, (blk*eeFsBlockSize)+eeFsBlocksOffset, eeFsLinkSize); + } uint8_t RleFile::EeFsGetDat(unsigned int blk, unsigned int ofs) @@ -244,10 +182,7 @@ unsigned int RleFile::EeFsGetFree() unsigned int ret = 0; unsigned int i; - if (IS_ARM(board)) - i = eeFsArm->freeList; - else - i = eeFs->freeList; + i = eeFsArm->freeList; while (i) { ret += eeFsBlockSize-eeFsLinkSize; @@ -266,14 +201,8 @@ void RleFile::EeFsFree(unsigned int blk) unsigned int i = blk; while (EeFsGetLink(i)) i = EeFsGetLink(i); - if (IS_ARM(board)) { - EeFsSetLink(i, eeFsArm->freeList); - eeFsArm->freeList = blk; //chain in front - } - else { - EeFsSetLink(i, eeFs->freeList); - eeFs->freeList = blk; //chain in front - } + EeFsSetLink(i, eeFsArm->freeList); + eeFsArm->freeList = blk; //chain in front } /* @@ -283,12 +212,9 @@ unsigned int RleFile::EeFsAlloc() { if (IS_FAMILY_HORUS_OR_T16(board)) return 0; - unsigned int ret = (IS_ARM(board) ? eeFsArm->freeList : eeFs->freeList); + unsigned int ret = eeFsArm->freeList; if (ret) { - if (IS_ARM(board)) - eeFsArm->freeList = EeFsGetLink(ret); - else - eeFs->freeList = EeFsGetLink(ret); + eeFsArm->freeList = EeFsGetLink(ret); EeFsSetLink(ret, 0); } return ret; @@ -299,7 +225,7 @@ unsigned int RleFile::size(unsigned int id) if (IS_FAMILY_HORUS_OR_T16(board)) return 0; else - return IS_ARM(board) ? eeFsArm->files[id].size : eeFs->files[id].size; + return eeFsArm->files[id].size; } unsigned int RleFile::openRd(unsigned int i_fileId) @@ -327,15 +253,12 @@ unsigned int RleFile::openRd(unsigned int i_fileId) else { m_fileId = i_fileId; m_pos = 0; - m_currBlk = (IS_ARM(board) ? eeFsArm->files[m_fileId].startBlk : eeFs->files[m_fileId].startBlk); + m_currBlk = eeFsArm->files[m_fileId].startBlk; m_ofs = 0; m_zeroes = 0; m_bRlc = 0; m_err = ERR_NONE; //error reasons - if (IS_ARM(board)) - return eeFsArm->files[m_fileId].typ; - else - return eeFs->files[m_fileId].typ; + return eeFsArm->files[m_fileId].typ; } } @@ -344,14 +267,14 @@ unsigned int RleFile::read(uint8_t *buf, unsigned int i_len) if (IS_FAMILY_HORUS_OR_T16(board)) return 0; - unsigned int len = IS_ARM(board) ? eeFsArm->files[m_fileId].size : eeFs->files[m_fileId].size; + unsigned int len = eeFsArm->files[m_fileId].size; len -= m_pos; if (i_len > len) i_len = len; len = i_len; while(len) { if (!m_currBlk) break; *buf++ = EeFsGetDat(m_currBlk, m_ofs++); - if (m_ofs >= (eeFsBlockSize-(IS_ARM(board)? 2 : 1))) { + if (m_ofs >= (eeFsBlockSize - 2)) { m_ofs = 0; m_currBlk = EeFsGetLink(m_currBlk); } @@ -492,10 +415,7 @@ unsigned int RleFile::write(const uint8_t *buf, unsigned int i_len) unsigned int len = i_len; if (!m_currBlk && m_pos==0) { - if (IS_ARM(board)) - eeFsArm->files[m_fileId].startBlk = m_currBlk = EeFsAlloc(); - else - eeFs->files[m_fileId].startBlk = m_currBlk = EeFsAlloc(); + eeFsArm->files[m_fileId].startBlk = m_currBlk = EeFsAlloc(); } while (len) { @@ -527,23 +447,15 @@ unsigned int RleFile::write(const uint8_t *buf, unsigned int i_len) void RleFile::create(unsigned int i_fileId, unsigned int typ) { openRd(i_fileId); //internal use - if (IS_ARM(board)) { - eeFsArm->files[i_fileId].typ = typ; - eeFsArm->files[i_fileId].size = 0; - } - else { - eeFs->files[i_fileId].typ = typ; - eeFs->files[i_fileId].size = 0; - } + eeFsArm->files[i_fileId].typ = typ; + eeFsArm->files[i_fileId].size = 0; + } void RleFile::closeTrunc() { unsigned int fri=0; - if (IS_ARM(board)) - eeFsArm->files[m_fileId].size = m_pos; - else - eeFs->files[m_fileId].size = m_pos; + eeFsArm->files[m_fileId].size = m_pos; if (m_currBlk && ( fri = EeFsGetLink(m_currBlk))) EeFsSetLink(m_currBlk, 0); if(fri) EeFsFree( fri ); //chain in } diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index fff65e6d9..9b18ec30e 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -743,58 +743,58 @@ Manche Droit: Profondeur, Direction Boards - + Left Horizontal Gauche Horizontal - + Left Vertical Gauche Vertical - + Right Vertical Droit Vertical - + Right Horizontal Droit Horizontal - + Aux. 1 - + Aux. 2 - - + + Unknown Inconnu - + Rud Dir - + Ele Prf - + Thr Gaz - + Ail @@ -908,57 +908,62 @@ Manche Droit: Profondeur, Direction Supprimer la Voie. Êtes-vous sûr? - + + Cut Channel. Are you sure? + Couper la Voie. Êtes-vous sûr? + + + Copy Copier - + Cut Couper - + Paste Coller - + Clear Effacer - + Insert Insérer - + Delete Supprimer - + Move Up Monter - + Move Down Descendre - + Clear All Effacer Tout - + Clear Channel. Are you sure? Effacer la Voie. Êtes-vous sûr? - + Clear all Channels. Are you sure? Effacer toutes les Voies. Êtes-vous sûr? @@ -1596,17 +1601,22 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Effacer Tout - + Clear Curve. Are you sure? Effacer la Courbe. Êtes-vous sûr? - + Clear all Curves. Are you sure? Effacer toutes les Courbes. Êtes-vous sûr? - + + Cut Curve. Are you sure? + Couper la Courbe. Êtes-vous sûr? + + + Delete Curve. Are you sure? Supprimer la Courbe. Êtes-vous sûr? @@ -1640,8 +1650,8 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import - Trainer - Écolage Manches + Trainer Sticks + Manches Écolage @@ -1784,79 +1794,79 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Bind module externe - + Timer1 Chrono 1 - + Timer2 Chrono 2 - + Timer3 Chrono 3 - + Flight Vol - + Telemetry Télémétrie - + Rotary Encoder Sélecteur Rotatif - + REa - + REb - + s - - - + + + <font color=red><b>Inconsistent parameter</b></font> <font color=red><b>Paramètre inconsistant</b></font> - + Value Valeur - + played once, not during startup !1x Lu une fois, mais pas à la mise en route - + repeat(%1s) Répéter chaque %1s - + DISABLED DESACTIVE - + CFN FPN @@ -1916,84 +1926,89 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import %1 - - Delete Special Function. Are you sure? - Supprimer la Fonction Spéciale. Êtes-vous sûr? + + Delete Function. Are you sure? + Supprimer la Fonction. Êtes-vous sûr? - + + Cut Special Function. Are you sure? + Couper la Fonction. Êtes-vous sûr? + + + Copy Copier - + Cut Couper - + Paste Coller - + Clear Effacer - + Insert Insérer - + Delete Supprimer - + Move Up Monter - + Move Down Descendre - + Clear All Effacer Tout - + Value Valeur - + Source Source - + GVAR VG - + Increment Incrément - - Clear Special Function. Are you sure? - Effacer la Fonction Spéciale. Êtes-vous sûr? + + Clear Function. Are you sure? + Effacer la Fonction. Êtes-vous sûr? - - Clear all Special Functions. Are you sure? - Supprimer toutes les Fonctions Spéciales. Êtes-vous sûr? + + Clear all Functions. Are you sure? + Effacer toutes les Fonctions. Êtes-vous sûr? @@ -2159,48 +2174,48 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Erreur de conversion du champ %1 - + Switch Interrupteur - + Switch L'interrupteur - + cannot be exported on this board! n'est pas supporté sur cette carte ! - + Source - + Source %1 cannot be exported on this board! La source %1 n'est pas supportée sur cette plateforme ! - + OpenTX only accepts %1 points in all curves OpenTX n'accepte que %1 points au maximum entre toutes les courbes - + OpenTx only accepts %1 points in all curves OpenTX n'accepte que %1 points au maximum entre toutes les courbes - - + + OpenTX on this board doesn't accept this function OpenTX ne supporte pas cette fonction sur cette carte - + OpenTX doesn't accept this radio protocol OpenTX ne supporte pas ce protocole radio @@ -2327,62 +2342,47 @@ Pour <b>retirer un filtre de l'historique</b>, sélectionnez-le - - Eeprom is not from Th9X - - L'EEPROM n'est pas une EEPROM TX9X - - - - - Eeprom is not from Gruvin9X - - L'EEPROM n'est pas une EEPROM Gruvin9X - - - - Eeprom is not from ErSky9X - L'EEPROM n'est pas une EEPROM ErSky9X - - - Eeprom is not from Er9X - - L'EEPROM n'est pas une EEPROM Er9X - - - + - Eeprom size is invalid - La taille de l'EEPROM est invalide - + - Eeprom file system is invalid - Le système de fichier de l'EEPROM est invalide - + - Eeprom is from a unknown board - L'EEPROM ne correspond à aucune carte supportée - + - Eeprom is from the wrong board - L'EEPROM ne correspond pas au type de radio sélectionné - + - Eeprom backup not supported - Sauvegarde d'EEPROM non supportée - + - Something that couldn't be guessed, sorry - Erreur inconnue - + Warning: Avertissement: - - + + - Your radio probably uses a wrong firmware, eeprom size is 4096 but only the first 2048 are used - Le firmware de la radio est probablement incorrect, @@ -2390,7 +2390,7 @@ la taille de l'EEPROM est de 4096 mais seulement 2048 bytes sont utilisés. Vérifier la sélection (M64/M128) - + - Your eeprom is from an old version of OpenTX, upgrading! To keep your original file as a backup, please choose File -> Save As specifying a different name. - Votre eeprom provient d'une ancienne version d'OpenTX, mettez à niveau! @@ -2553,22 +2553,22 @@ Si vide, la ligne est toujours active. Éditer %1 - + Popup menu available Menu contextuel disponible - + Clear All Effacer Tout - + Set All Définir Tout - + Invert All Inverser Tout @@ -2937,282 +2937,258 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Firmware - + Channel values displayed in us Positions de voies affichées en µs - + No OverrideCH functions available Désactive la fonction spéciale "Remplacer VOIExx" - + Possibility to enable FAI MODE (no telemetry) at field Possibilité d'activer le mode FAI (télémétrie désactivée) sur le terrain - + FAI MODE (no telemetry) always enabled Mode FAI (télémétrie toujours désactivée) - + Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015 Masque le protocole D8. Légalement obligatoire sur les radios Européennes importées après le 1er janvier 2015 - - + + Disable HELI menu and cyclic mix support Supprimer le menu HELICO et les mixages cycliques - - + + Disable Global variables Supprimer le support des variables globales - - + + Enable Lua custom scripts screen Activer l'écran des scripts Lua personnalisés - - Support for PPM internal module hack - Support du remplacement du module interne par un module PPM - - - + Use alternative SQT5 font Utiliser la police alternative SQT5 - - + + Disable RAS (SWR) Désactiver le RAS (SWR). Utile uniquement pour les X9D+ avec un RAS/SWR non fonctionnel - + Pots use in menus navigation Support de la navigation dans les menus avec les POTS - + + Enable AFHDS3 support + Activer le support du AFHDS3 + + + FrSky Taranis X9D+ - + FrSky Taranis X9D+ 2019 - + FrSky Taranis X9D - + Haptic module installed Module vibreur installé - + FrSky Taranis X9E - + Confirmation before radio shutdown Confirmation avant l'arrêt de la radio - + Horus gimbals installed (Hall sensors) Manches Horus à effet HALL installés - + FrSky Taranis X9-Lite - + FrSky Taranis X9-Lite S - + FrSky Taranis X7 / X7S - + FrSky Taranis X7 / X7S Access - + FrSky Taranis X-Lite S/PRO - + FrSky Taranis X-Lite - + FrSky Horus X10 / X10S - - + + Support for ACCESS internal module replacement Prise en charge du module de remplacement interne ACCESS - + FrSky Horus X10 Express / X10S Express - + FrSky Horus X12S - + Use ONLY with first DEV pcb version Exclusivement pour les Horus DEV - - + + Support for MULTI internal module Prise en charge du module MULTI interne - - + + + Support for bluetooth module Prise en charge du module Bluetooth - + Radiomaster TX16s / TX16s Hall / TX16s Masterfire - + Support internal GPS Prise en charge du GPS interne - + + Jumper T18 + + + + Turnigy 9XR-PRO - + Enable HELI menu and cyclic mix support Activer le menu hélico et les mixages CCPM - + Global variables Variables globales - + Enable non certified firmwares Activer les firmwares non certifiés - + In model setup menus automatically set source by moving the control Sélectionner les sources des mixeurs en bougeant le contrôle désiré - + In model setup menus automatically set switch by moving the control Sélectionner les interrupteurs en bougeant le contrôle désiré - + No graphical check boxes and sliders Pas de cases à cocher et de curseurs graphiques - + Battery graph Graphique de la batterie - + Don't use bold font for highlighting active items Ne pas mettre les lignes actives en gras - - Turnigy 9XR with m128 chip - Turnigy 9XR avec une puce m128 - - - - Turnigy 9XR - - - - - 9X with stock board - 9X avec carte mère d'origine - - - + Enable resetting values by pressing up and down at the same time Permet la remise à zéro des valeurs en pressant haut-bas en même temps, valeur min avec gauche/bas, valeur max avec haut/droite, inversion avec gauche/droite - - 9X with stock board and m128 chip - Carte 9x avec un chip m128 - - - + 9X with AR9X board 9X avec carte AR9X - + Jumper T12 / T12 Pro - + Jumper T16 / T16+ / T16 Pro - + 9X with Sky9x board 9X avec carte Sky9x - - - 9X with Gruvin9x board - 9X avec carte Gruvin9x - - - - DIY MEGA2560 radio - Radio DIY à base de MEGA2560 - FirmwarePreferencesDialog @@ -3471,62 +3447,62 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Transférer - + Open Firmware File Sélectionner le firmware - + %1 may not be a valid firmware file %1 ne semble pas être un firmware valide - + The firmware file is not valid. Le firmware est invalide. - + There is no start screen image in the firmware file. Aucun écran d'accueil trouvé dans le firmware. - + Profile image %1 is invalid. L'image du profil %1 est invalide. - + Open image file to use as radio start screen Ouvrir l'image à utiliser comme écran d'accueil - + Images (%1) Images (%1) - + Image could not be loaded from %1 L'image %1 n'a pu être chargée - + The library image could not be loaded L'image n'a pu être chargée depuis la bibliothèque - + Splash image not found Ecran d'accueil sélectionné introuvable - + Cannot save customized firmware Impossible d'enregistrer le firmware personnalisé - + Write Firmware to Radio Transférer le firmware à la radio @@ -3547,27 +3523,27 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Le nouveau firmware ne correspond pas à la version installée, vérifiez le type de radio ! - + Conversion failed La conversion a échoué - + Cannot convert Models and Settings for use with this firmware, original data will be used Impossible de convertir les paramètres et modèles pour ce firmware, les données originales vont être utilisées - + Restore failed Echec de la restauration - + Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1 Impossible de restaurer les paramètres et modèles sur la radio. Le fichier peut être récupéré ici: %1 - + Flashing done Programmation terminée @@ -3580,42 +3556,42 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Exécutable %1 introuvable - + Writing... Ecriture... - + Reading... Lecture... - + Verifying... Vérification... - + unknown inconnu - + ie: OpenTX for 9X board or OpenTX for 9XR board ex: OpenTX pour carte d'origine 9x ou OpenTX pour 9XR - + ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip ex:. OpenTX pour carte d'origine 9x avec m128 ou OpenTX pour 9XR avec m128 - + ie: OpenTX for Gruvin9X board ex: OpenTX pour carte gruvin9x - + Your radio uses a %1 CPU!!! Please check advanced burn options to set the correct cpu type. @@ -3624,7 +3600,7 @@ Please check advanced burn options to set the correct cpu type. Vérifiez les options de programmateur et choisissez le bon type de processeur. - + Your radio uses a %1 CPU!!! Please select an appropriate firmware type to program it. @@ -3633,7 +3609,7 @@ Please select an appropriate firmware type to program it. Veuillez choisir le firmware approprié. - + You are currently using: %1 @@ -3642,22 +3618,22 @@ Vous utilisez actuellement: %1 - + Your radio does not seem connected to USB or the driver is not initialized!!!. Votre radio ne semble pas être connectée en USB, ou le pilote n'est pas initialisé !!!. - + Flashing done (exit code = %1) Terminé (code de sortie = %1) - + Flashing done with errors Terminé avec des erreurs - + FUSES: Low=%1 High=%2 Ext=%3 Fusibles: Bas=%1 Haut=%2 Ext=%3 @@ -3762,79 +3738,109 @@ Vous utilisez actuellement: - + Copy Copier - + Cut Couper - + Paste Coller - + Insert Insérer - + Delete Supprimer - + Move Up Monter - + Move Down Descendre - + Clear All Effacer Tout - + Clear Flight Mode. Are you sure? Effacer la Phase de Vol. Êtes-vous sûr? - + Clear all Flight Modes. Are you sure? Effacer toutes les Phases de Vol. Êtes-vous sûr? - + + Cut Flight Mode. Are you sure? + Couper la Phase de Vol. Êtes-vous sûr? + + + Delete Flight Mode. Are you sure? Supprimer la Phase de Vol. Êtes-vous sûr? - - Clear selected Global Variable across all Flight Modes. Are you sure? - Effacer les Variables Globales selectionnées à travers toutes les Phases de Vol. Êtes-vous sûr? + + Clear Global Variable across all Flight Modes. Are you sure? + Effacer la Variable Globale pour toutes les Phases de Vol. Êtes-vous sûr? - + + Clear Global Variable. Are you sure? + Effacer la Variable Globale. Êtes-vous sûr? + + + + Cut Global Variable across all Flight Modes. Are you sure? + Couper la Variable Globale pour toutes les Phases de Vol. Êtes-vous sûr? + + + + Cut Global Variable. Are you sure? + Couper la Variable Globale. Êtes-vous sûr? + + + + Delete Global Variable. Are you sure? + Supprimer la Variable Globale. Êtes-vous sûr? + + + + Paste to selected Global Variable across all Flight Modes. Are you sure? + Coller la Variable Globale pour toutes les Phases de Vol. Êtes-vous sûr? + + + Clear all Global Variables for all Flight Modes. Are you sure? Effacer toutes les Variables Globales pour toutes les Phases de Vol. Êtes-vous sûr? - + Clear all Global Variables for this Flight Mode. Are you sure? Effacer toutes les Variables Globales pour cette Phase de Vol. Êtes-vous sûr? @@ -3881,7 +3887,7 @@ Vous utilisez actuellement: - + Clear Effacer @@ -3889,17 +3895,17 @@ Vous utilisez actuellement: FlightModesPanel - + Flight Mode %1 Phase de vol %1 - + (%1) - + (default) (par défaut) @@ -4169,7 +4175,7 @@ These will be relevant for all models in the same EEPROM. Communs à tous les modèles d'une même EEPROM. - + Trainer Écolage @@ -4184,42 +4190,42 @@ Communs à tous les modèles d'une même EEPROM. Lire étalonnage et paramètres hw du profil - + Global Functions Fonctions globales - + Hardware Matériel - + Calibration - + Wrong data in profile, radio calibration was not retrieved Données du profil erronnées, l'étalonnage n'a pas été lu - + Wrong data in profile, Switch/pot config not retrieved Données incorecte, Interrupteurs/Pot non trouvés - + Wrong data in profile, hw related parameters were not retrieved Données du profil erronnées, les paramètres hw n'ont pas été lus - + Do you want to store calibration in %1 profile<br>overwriting existing calibration? Voulez-vous stocker l'étalonnage dans le profil %1<br> et écraser l'étalonnage existant ? - + Calibration and HW parameters saved. Etalonnage et paramètres hw enregistrés avec succès. @@ -4227,7 +4233,7 @@ Communs à tous les modèles d'une même EEPROM. GeneralSettings - + Radio Settings Paramètres de la radio @@ -4285,169 +4291,169 @@ Communs à tous les modèles d'une même EEPROM. - + Timeshift from UTC Décalage horaire (UTC) - + Voice Language Langue des voix - + Country Code Zone géographique RF - + Stick reverse Inversion des manches - + FAI Mode Mode FAI - + Adjust RTC Ajuster l'heure par GPS - + Vario pitch at max Tonalité du vario au max - - + + Hz - + Speaker Volume Volume haut-parleur - + Backlight Switch Inter de rétroéclairage - + Sound Mode Mode Son - + Color 1 Couleur 1 - + Color 2 Couleur 2 - + Speaker Pitch (spkr only) Tonalité (HP uniquement) - + If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds. Si cette valeur est différente de 0, l'appui sur une touche de navigation déclenche le rétroéclairage qui s'éteint après la durée spécifiée (en secondes). - - - + + + sec - + Backlight color Couleur du rétroéclairage - + Beeper Bipeur - + Speaker Haut-parleur - + BeeperVoice Bipeur/Voix - + SpeakerVoice Haut-parleur/Voix - + Beep volume Volume des bips - + Wav volume Volume des fichiers audio - + Vario volume Volume du variomètre - + Background volume Volume de la musique d'ambiance - - + + ms - + Backlight Auto OFF after Arrêt rétroéclairage après - + Backlight flash on alarm Clignotement rétroécl. alarmes - + Vario pitch at zero Tonalité du vario à 0 - + Vario repeat at zero Répétition du vario à 0 - + This is the switch selectrion for turning on the backlight (if installed). Interrupteur déclenchant le rétroéclairage' (si installé). - - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -4462,42 +4468,42 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Plage de valeurs: 20...45</span></p></body></html> - + Backlight Brightness Luminosité du rétroéclairage - + RotEnc Navigation Navigation sélecteur rotatif - + Automatically adjust the radio's clock if a GPS is connected to telemetry. Régle automatique l'heure de la radio si un GPS est présent. - + America Amérique - + Japan Japon - + Europe - + Backlight OFF Brightness Luminosité écran éteint - + Mode selection: Mode 1: @@ -4538,332 +4544,337 @@ Mode 4: - + Mode 1 (RUD ELE THR AIL) Mode 1 (DIR PRF GAZ AIL) - + Mode 2 (RUD THR ELE AIL) Mode 2 (DIR GAZ PRF AIL) - + Mode 3 (AIL ELE THR RUD) Mode 3 (AIL PRF GAZ DIR) - + Mode 4 (AIL THR ELE RUD) Mode 4 (AIL GAZ PRF DIR) - + <html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html> <html><head/><body><p>Ordre des voies</p><p><br/></p><p>Détermine l'ordre des mixages par défaut sur un nouveau modèle.</p></body></html> - + If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. Si vous activez l'option FAI, seuls les capteurs RSSI et BtRx vont fonctionner. Cette fonction ne peut pas être désactivée sur la radio. - + Owner Registration ID Enregistrement ID du propriétaire - + + Keys Backlight + Rétroéclairage des touches + + + R E T A D P G A - + R E A T D P A G - + R T E A D G P A - + R T A E D G A P - + R A E T D A P G - + R A T E D A G P - + E R T A P D G A - + E R A T P D A G - + E T R A P G D A - + E T A R P G A D - + E A R T P A D G - + E A T R P A G D - + T R E A G D P A - + T R A E G D A P - + T E R A G P D A - + T E A R G P A D - + T A R E G A D P - + T A E R G A P D - + A R E T A D P G - + A R T E A D G P - + A E R T A P D G - + A E T R A P G D - + A T R E A G D P - + A T E R A G P D - + Power Off Delay Délai mise hors tension - + USB Mode Mode USB - + Jack Mode Mode Jack - + Audio - + Trainer Écolage - - + + Ask on Connect Demander à la connexion - + Joystick (HID) - + USB Mass Storage Stockage USB (SD) - + USB Serial (CDC) Port série USB (Debug) - + Stick Mode Mode - + Metric Métrique - + Imperial Impérial - + Default Channel Order Ordre des voies par défaut - + GPS Coordinates Coordonnées GPS - + Min - - + + v - + Max - + RSSI Poweroff Warning Vérifier RSSI à l'extinction - + DMS - + Inactivity Timer Alerte d'inactivité - + Show Splash Screen on Startup Afficher l'écran de démarrage - + Contrast Contraste - + Battery Meter Range Plage de l'indicateur de batterie - + Haptic Strength Puissance vibreur - + LCD Display Type Type de LCD - + "No Sound" Warning Alerte "son coupé" - + Battery Warning Alerte batterie - + Haptic Length Durée vibreur - + MAVLink Baud Rate Baudrate Mavlink - - + + Quiet Mode silencieux - + Only Alarms Seulement les alarmes - - + + No Keys Touches silencieuses - - + + All Tous - + Battery warning voltage. This is the threashhold where the battery warning sounds. @@ -4874,126 +4885,126 @@ Seuil auquel se déclenche l'alarme de batterie. Plage de valeurs: 5v...10v - + Standard - + Optrex - + If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes. Si différent de 0, émission d'un bip sonore régulier si aucune action n'a été effectuée sur l'émetteur depuis le temps spécifié (en minutes). Réinitialisation en agissant sur n'importe lequel des manches / touches de navigation. - + nnnnnnNN - + min - + Power On Delay Délai mise sous tension - - + + Show splash screen on startup Affiche l'écran d'accueil au démarrage - + --- - + 2s - + 3s - + 4s - + 6s - + 8s - + 10s - + 15s - + 4800 Baud - + 9600 Baud - + 14400 Baud - + 19200 Baud - + 38400 Baud - + 57600 Baud - + 76800 Baud - + 115200 Baud - - - + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -5018,72 +5029,72 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Alerte mode silencieux - Avertissement si les bips sont désactivés</p></body></html> - - + + X-Short Très court - - + + Short Court - - + + Normal - - + + Long - - + + X-Long Très long - + Low EEPROM Warning Avertissement EEPROM faible - + NMEA - + Play Delay (switch mid position) Délai position centrale inters - + Measurement Units Unités de mesure - + Haptic Mode Mode du vibreur - + Beeper Length Durée des bips - + Beeper Mode Paramètre des bips - + Beeper volume 0 - Quiet. No beeps at all. @@ -5100,7 +5111,7 @@ Long : bips plus longs. Extra long : bips extra longs. - + Alarms Only Seulement les Alarmes @@ -5108,127 +5119,127 @@ Extra long : bips extra longs. GeneralSetupPanel - + OFF - + Keys Touches - + Sticks Manches - + Keys + Sticks Touches + manches - + ON - + English Anglais - + Dutch Hollandais - + French Français - + Italian Italien - + German Allemand - + Czech Tchèque - + Slovak Slovaque - + Spanish Espagnol - + Polish Polonais - + Portuguese Portugais - + Swedish Suédois - + Hungarian Hongrois - + Russian Russe - + No Non - + RotEnc A Sel.Rot. A - + Rot Enc B Sel.Rot. B - + Rot Enc C Sel.Rot. C - + Rot Enc D Sel.Rot. D - + Rot Enc E Sel.Rot. E - + If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. Are you sure ? @@ -5760,9 +5771,14 @@ Cette fonction ne peut pas être désactivée sur la radio. Pas assez d'Entrées disponibles! - - Delete selected Inputs. Are you sure? - Supprimer les Entrées selectionnés. Êtes-vous sûr? + + Delete selected Input lines. Are you sure? + Supprimer les lignes Entrée sélectionnées. Êtes-vous sûr? + + + + Cut selected Input lines. Are you sure? + Couper les lignes Entrée sélectionnées. Êtes-vous sûr? @@ -5862,18 +5878,18 @@ Cette fonction ne peut pas être désactivée sur la radio. - Clear all Inputs. Are you sure? - Effacer toutes les Entrées. Êtes-vous sûr? + Clear all Input lines. Are you sure? + Effacer toutes les lignes Entrée. Êtes-vous sûr? - Clear Input. Are you sure? - Effacer l'Entrée. Êtes-vous sûr? + Clear all lines for the selected Inputs. Are you sure? + Effacer toutes les lignes Entrée sélectionnées. Êtes-vous sûr? - Delete Input. Are you sure? - Supprimer l'Entrée. Êtes-vous sûr? + Delete all lines for the selected Inputs. Are you sure? + Supprimer toutes les lignes Entrée sélectionnées. Êtes-vous sûr? @@ -6073,57 +6089,67 @@ Cette fonction ne peut pas être désactivée sur la radio. (infini) - + Delete Logical Switch. Are you sure? Supprimer l'Interrupteur Logique. Êtes-vous sûr? - + + Cut Logical Switch. Are you sure? + Couper l'Interrupteur Logique. Êtes-vous sûr? + + + Copy Copier - + Cut Couper - + Paste Coller - + Clear Effacer - + Insert Insérer - + Delete Supprimer - + Move Up Monter - + Move Down Descendre - + Clear All Effacer Tout - + + Clear Logical Switch. Are you sure? + Effacer l'Interrupteur Logique. Êtes-vous sûr? + + + Clear all Logical Switches. Are you sure? Effacer tous les Interrupteurs Logiques. Êtes-vous sûr? @@ -6305,79 +6331,74 @@ Les colonnes contenant l'altitude "GAlt" et la vitesse "GSpd MainWindow - - + + Edit Édition - - + + File Fichier - + New release available Nouvelle version disponible - + Error opening file %1: %2. Erreur à l'ouverture du fichier %1: %2. - + Compilation server too busy, try later Serveur de compilation surchargé, veuillez réessayer plus tard - + Unknown server failure, try later Erreur inconnue du serveur de compilation, veuillez réessayer plus tard - + Do you want to write the firmware to the radio now ? Voulez vous transférer le firmware à la radio maintenant ? - - + + Yes Oui - - + + No Non - - + + Release Notes Notes de version - + Compare models Comparer les modèles - - Show fuses dialog - Afficher les paramètres des fusibles - - - + A monochrome black icon theme Thème avec icônes monochromes noires - + A new version of %1 firmware is available: - current is %2 - newer is %3 @@ -6394,511 +6415,501 @@ Voulez vous la télécharger maintenant ? Nous recommandons de lire attentivement les notes de version à l'aide du bouton ci-dessous, celles-ci peuvent contenir des infos importantes concernant les changements effectués depuis la version précédente. - - + + Synchronize SD Synchroniser la carte SD - + New Nouveau - + Open... Ouvrir... - + A monochrome white icon theme Thème avec icônes monochromes blanches - + A monochrome blue icon theme Thème avec icônes monochromes bleues - + Small Petites - + Use small toolbar icons Petites icônes de barre d'outils - + Use normal size toolbar icons Icônes de barre d'outils normales - + Normal Normales - + Use big toolbar icons Grosses icônes de barre d'outils - + Big Grandes - + Use huge toolbar icons Immenses icônes de barre d'outils - + Huge Immenses - - List programmers... - Lister les programmateurs... - - - - Fuses... - Fusibles... - - - - + + Read Firmware from Radio Lire le firmware de la radio - + Read firmware from Radio Lire le firmware de la radio - + Write Firmware to Radio Transférer le firmware à la radio - + Write firmware to Radio Transférer le firmware à la radio - + Add Radio Profile Ajouter un profil de radio - + Manuals and other Documents Manuels et documents - + Open the OpenTX document page in a web browser Ouvre la page de documentation d'OpenTX dans un navigateur - + Write Models and Settings To Radio Transférer les paramètres et modèles vers la radio - + Write Models and Settings to Radio Transférer les paramètres et modèles vers la radio - - + + Read Models and Settings from Radio Lire les paramètres et modèles depuis la radio - + OpenTX Companion %1 - Radio: %2 - Profile: %3 OpenTX Companion %1 - Radio: %2 - Profil: %3 - + List of recently used files Liste des fichiers récemment utilisés - + Radio Profiles Profil radio - + Create or Select Radio Profiles Créer ou Sélectionner un profil radio - + Configure Communications... Configurer les communications... - + Configure software for communicating with the Radio Configurer le programme gérant les communications avec la radio - + Write Backup to Radio Transférer une sauvegarde à la radio - + Write Backup from file to Radio Transférer une sauvegarde à la radio - + Backup Radio to File Sauvegarder la radio - + Save a complete backup file of all settings and model data in the Radio Créer une copie de sauvegarde de tous les paramètres et modèles de la radio - + Contributors... Contributeurs... - + A tribute to those who have contributed to OpenTX and Companion Remerciements à tout ceux qui ont contribué à OpenTX et Companion - + SD card synchronization Synchronisation de la carte SD - + Recent Files Fichiers récents - + Set Icon Theme Choisir le thème d'icônes - + Set Icon Size Choisir la taille des icônes - + Write Ecrire - + A new version of Companion is available (version %1)<br>Would you like to download it? Une nouvelle version de Companion est disponible (version %1)<br>Voulez-vous la télécharger ? - + OpenTX Home Page: <a href='%1'>%1</a> Page d'accueil d'OpenTX: <a href='%1'>%1</a> - + If you've found this program useful, please support by <a href='%1'>donating</a> Si vous trouvez ce programme utile, merci de le supporter par une <a href='%1'>donation</a> - + Ready Prêt - + Show the application's About box Afficher la fenêtre "A propos" de l'application - - + + File loaded Fichier chargé - - + + Open Models and Settings file Ouvrir un fichier de paramètres et modèles - - + + File saved Fichier sauvegardé - + Read Models and Settings From Radio Lire les paramètres et modèles depuis la radio - + Not enough flash available on this board for all the selected options Pas assez de place disponible pour les options sélectionnées - + Compilation server temporary failure, try later Erreur de compilation sur le serveur, veuillez réessayer plus tard - + Compilation error Erreur de compilation - + Invalid firmware Firmware invalide - + Invalid board Carte non valide - + Invalid language Language non valide - + Some text will not be translated until the next time you start Companion. Please note that some translations may not be complete. Certains textes ne seront pas traduits avant le prochain redémarrage de Companion. Veuillez noter que certaines traductions peuvent ne pas être complètes. - + Models and Settings read Lecture des modèles et paramètres - + Companion update check failed, new version information not found. La vérification de mise à jour de Companion a échoué, les infos sur une nouvelle version sont introuvables. - + Firmware update check failed, new version information not found or invalid. La vérification de mise à jour du Firmware a échoué, les infos sur une nouvelle version sont introuvables ou invalides. - + Local Folder Dossier "Local" - + Radio Folder Dossier "Radio" - - + + This function is not yet implemented Cette fonction n'est pas implémentée pour l'instant - + Save Radio Backup to File Sauvegarder la radio - + Read Radio Firmware to File Sauvegarder le firmware de la radio - + The OpenTX Companion project was originally forked from <a href='%1'>eePe</a> Le projet OpenTX Companion a été créé à partir d'<a href='%1'>eePe</a> - + Copyright OpenTX Team - + Create a new Models and Settings file Créer un nouveau fichier de paramètres et modèles - - + + Save Models and Settings file Enregistrer le fichier de paramètres et modèles - + Save Enregistrer - + Save As... Enregistrer sous... - + Close Fermer - + Close Models and Settings file Fermer le fichier de paramètres et modèles - + Exit the application Quitter l'application - + Exit Quitter - + Create a new Radio Settings Profile Créer un nouveau profil de paramètres et modèles - + Copy Current Radio Profile Copier le profil radio actuel - + Duplicate current Radio Settings Profile Dupliquer les paramètres radio du profil actuel - + Delete the current Radio Settings Profile Supprimer les paramètres radio du profil actuel - + Use default system language. Utiliser le langage système par défaut. - + Use %1 language (some translations may not be complete). Utiliser la langue %1 (certaines traductions peuvent être incomplètes). - + Classical Classique - + Diskimage (*.dmg) Image disque (*.dmg) - + Would you like to open the disk image to install the new version? Voulez-vous ouvrir l'image disque afin d'installer la nouvelle version ? - + Executable (*.exe) Exécutable (*.exe) - - + + Would you like to launch the installer? Voulez-vous lancer l'installateur ? - + No Companion release candidates are currently being served for this version, please switch release channel Aucune version "candidate" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" - + No nightly Companion builds are currently being served for this version, please switch release channel Aucune version "nightly" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" - + No Companion release builds are currently being served for this version, please switch release channel Aucune version "officielle" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "candidate" ou "nightly" - + A new release of Companion is available, please check the <a href='%1'>OpenTX website!</a> Une nouvelle version de Companion est disponible, vérifiez le site OpenTX <a href='%1'> !</a> - + No firmware release candidates are currently being served for this version, please switch release channel Aucun firmware "candidate" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" - + No firmware nightly builds are currently being served for this version, please switch release channel Aucun firmware "nightly" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" - + No firmware release builds are currently being served for this version, please switch release channel Aucun firmware "officiel" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "candidate" ou "nightly" - + Release candidate builds are now available for this version, would you like to switch to using them? Une version "candidate" est maintenant disponible pour cette version, voulez-vous commuter de canal afin de l'utiliser? - + Channel changed to RC, please restart the download process Canal commuté sur "candidate", veuillez redémarrer le processus de téléchargement - + Official release builds are now available for this version, would you like to switch to using them? Une version "officielle" est maintenant disponible pour cette version, voulez-vous commuter de canal afin de l'utiliser? - + Channel changed to Release, please restart the download process Canal commuté sur "officiel", veuillez redémarrer le processus de téléchargement - + This radio (%1) is not currently available in this firmware release channel Le firmware pour cette radio (%1) n'est actuellement pas disponible dans le canal "officiel" - + Firmware %1 does not seem to have ever been downloaded. Version %2 is available. Do you want to download it now? @@ -6911,18 +6922,18 @@ Voulez-vous le télécharger maintenant? Nous vous recommandons de consulter les notes de mise à jour à l'aide du bouton ci-dessous pour en savoir plus sur les modifications susceptibles de vous intéresser. - - + + Do you want to download version %1 now ? Voulez-vous télécharger la version %1 maintenant? - + Ignore this version %1? Ignorer cette version %1? - + There are unsaved file changes which you may lose when switching radio types. Do you wish to continue? @@ -6931,355 +6942,350 @@ Do you wish to continue? Êtes-vous sûr de vouloir continuer ? - + No local SD structure path configured! Aucun chemin de configuré pour la structure SD en local ! - + No Radio or SD card detected! Pas de Radio ou carte SD de détectée ! - + Release notes... Notes de version... - + Show release notes Afficher les notes de version - + Delete Current Radio Profile... Supprimer le profil radio actuel... - + Export Application Settings.. Exporter Préférences Application... - + Save all the current %1 and Simulator settings (including radio profiles) to a file. Enregistrez tous les paramètres actuels %1 et du simulateur (y compris les profils radio) dans un fichier. - + Import Application Settings.. Importer les paramètres de l'application... - + Load %1 and Simulator settings from a prevously exported settings file. Charger les paramètres %1 et les paramètres de Simulation depuis un fichier précédemment exporté. - + Tabbed Windows Fenêtres à onglets - + Use tabs to arrange open windows. Utilisez les onglets pour organiser les fenêtres ouvertes. - + Tile Windows Titre de la fenêtre - + Arrange open windows across all the available space. Disposez les fenêtres ouvertes sur tout l'espace disponible. - + Cascade Windows Fenêtres en cascade - + Arrange all open windows in a stack. Organisez toutes les fenêtres ouvertes dans une pile. - + Close All Windows Fermer toutes les fenêtres - + Closes all open files (prompts to save if necessary. Fermer tous les fichiers ouverts (proposer de sauvegarder si nécessaire). - + Window Fenêtre - + Ctrl+Shift+S - + Ctrl+Alt+L - + Ctrl+Alt+D - + Ctrl+Alt+R - + The classic companion9x icon theme Thème d'icônes classique de Companion - + Yerico - + Yellow round honey sweet icon theme Thème d'icônes rondes jaunes - + Monochrome - + MonoWhite Monochrome Blanc - + Alt+%1 - + - Copy - Copier - + Companion :: Open files warning Companion::Ouvrir les fichiers d'avertissement - + Please save or close modified file(s) before deleting the active profile. Veuillez sauvegarder ou fermer le(s) fichier(s) modifié(s) avant de supprimer le profil actif. - + Not possible to remove profile Impossible de supprimer le profil - + The default profile can not be removed. Le profil par défaut ne peut pas être supprimé. - + Confirm Delete Profile Confirmer la suppression du profil - + Are you sure you wish to delete the "%1" radio profile? There is no way to undo this action! Etes-vous sûr de vouloir supprimer le profil radio %1? Cette action est irréversible! - + Please save or close all modified files before importing settings Veuillez sauvegarder ou fermer tous les fichiers modifiés avant d'importer les paramètres - + <html><p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. This will replace current settings with any settings found in the file.</p><p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p><p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p><p>Do you wish to continue?</p></html> <html><p>%1 et les paramètres du simulateur peuvent être importés (restaurés) à partir d’un fichier d’exportation (sauvegarde) préalablement sauvegardé. Ceci remplacera les paramètres actuels par tous les paramètres trouvés dans le fichier.</p><p>Une sauvegarde automatique des paramètres actuels sera tentée. Mais si les paramètres actuels sont utiles, il est recommandé de commencer par une sauvegarde manuelle.</p><p>Pour obtenir de meilleurs résultats lors de l'importation des paramètres,<b> fermez les autres fenêtres %1 que vous avez éventuellement ouvertes et assurez-vous que l'application autonome Simulator n'est pas en cours d'exécution. </p><p>Souhaitez-vous continuer? </p></html> - + Confirm Settings Import Confirmer les paramètres d'importation - + Select %1: Sélectionnez %1: - + backup sauvegarde - + Press the 'Ignore' button to continue anyway. Appuyez sur le bouton 'Ignorer' pour continuer quand même. - + The settings could not be imported. Les paramètres n'ont pas pu être importés. - + <html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p> <html><p>Les nouveaux paramètres ont été importés depuis:<br> %1. </p><p>%2 sera maintenant réinitialisé.</p><p>Notez que vous devrez peut-être fermer et redémarrer %2 avant que certains paramètres tels que la langue et le thème d’icône prennent effet.</p> - + <p>The previous settings were backed up to:<br> %1</p> <p>Les paramètres précédents ont été sauvegardés sous:<br> %1 </p> - + MonoBlue Monochrome Bleu - + System language Langue du système - + About... A propos... - + View Log File... Ouvrir un Log... - + Open and view log file Ouvrir et visualiser un log - + Settings... Préférences... - + Edit Settings Éditer les préférences - + Download... Télécharger... - + Download firmware and voice files Télécharger firmware et fichiers son - + Check for Updates... Vérifier les mises à jour... - + Check OpenTX and Companion updates Vérifier les mises à jour d'OpenTX et Companion - + Compare Models... Comparer 2 modèles... - + Edit Radio Splash Image... Éditer l'écran d'accueil de la radio... - + Edit the splash image of your Radio Éditer l'écran d'accueil de la radio - - List available programmers - Lister les programmateurs supportés - - - - + + Save As Enregistrer Sous - - + + No updates available at this time. Aucune mise à jour disponible. - - + + Help Aide - + Checking for updates Recherche de mises à jour - + The new theme will be loaded the next time you start Companion. Le nouveau thème sera utilisé lors du prochain lancement de Companion. - + About Companion A propos de Companion - + Set Menu Language Choisir la langue des menus - + Settings Paramètres - + Read/Write Transfert - + %2 - + New Radio Nouvelle radio @@ -7937,25 +7943,25 @@ Mixage actif par défaut si non-renseigné. MixesPanel - + Move Up Monter - + Ctrl+Up Ctrl+Haut - + Move Down Descendre - + Ctrl+Down Ctrl+Bas @@ -7970,97 +7976,102 @@ Mixage actif par défaut si non-renseigné. Plus de mixages disponibles ! - - Delete Selected Mixes? - Supprimer les mixages sélectionnés ? + + Delete selected Mix lines. Are you sure? + Supprimer les lignes Mixeur sélectionnées. Êtes-vous sûr? - + + Cut selected Mix lines. Are you sure? + Couper les lignes Mixeur sélectionnées. Êtes-vous sûr? + + + &Add &Ajouter - + Ctrl+A - + &Edit &Édition - + Enter Entrée - + Ctrl+T - + &Toggle highlight &(Dé)sélectionner - + &Delete &Supprimer - + Delete Supprimer - + &Copy &Copier - + Ctrl+C - + Ctrl+X - + C&ut &Couper - + &Paste &Coller - + Ctrl+V - + Du&plicate &Dupliquer - + Ctrl+U - + Clear Mixes? Effacer tous les mixages ? - + Really clear all the mixes? Êtes-vous sûr de vraiment vouloir effacer tous les mixages ? @@ -8068,12 +8079,12 @@ Mixage actif par défaut si non-renseigné. ModelData - + Model: Modèle: - + Throttle Source Source des gaz @@ -8174,27 +8185,27 @@ Mixage actif par défaut si non-renseigné. Inconnu - + Slave/Jack Elève/Jack - + Master/SBUS Module Maître/SBUS module - + Master/CPPM Module Maître/CPPM Module - + Master/SBUS in battery compartment Maître/SBUS compartiment batterie - + Master/Jack Maître/Jack @@ -8235,9 +8246,9 @@ Mixage actif par défaut si non-renseigné. - - - + + + OFF @@ -8248,7 +8259,7 @@ Mixage actif par défaut si non-renseigné. - + Mode @@ -8282,14 +8293,14 @@ Mixage actif par défaut si non-renseigné. - - + + Delay Délai - + Receiver Récepteur @@ -8315,581 +8326,592 @@ Mixage actif par défaut si non-renseigné. + RF Output Power Puissance RF - + + Output Type + Type de sortie + + + + RX Output Frequency + Fréquence de sortie du RX + + + 90 - + 120 - + 120X - + 140 - + MULT! - - + + Offset Décalage - + Slow Ralenti - + Warn Attn - + Flight modes Phases de vol - + Flight mode Phase de vol - + All Tous - + Edge Flanc - + Sticky Bistable - + Timer Chrono - + missing absent - + Duration Durée - + Extended Limits Limites étendues - + Display Checklist Afficher la checklist - + Global Functions Fonctions globales - + Manual Manuel - + Auto - + Failsafe Mode Mode Failsafe - - + + Hold Maintien - + No Pulse Pas d'impulsion - + Not set Non défini - + No pulses Pas d'impulsions - + Silent Aucun - + Beeps Bips - + Voice Voix - + Haptic Vibreur - + Flight Vol - + Manual reset RAZ manuelle - + Step Pas - + Display Affichage - + Extended Étendu - + Never Jamais - + On Change Sur changement - + Always Toujours - - - + + + Source - + Trim idle only Trim ralenti uniquement - + Warning Avertissement - + Reversed Inversé - + Tmr Chrono - + FrSky S.PORT - + FrSky D - + FrSky D (cable) FrSky D (câble) - + Alti Alt - + Alti+ Alt+ - + VSpeed Vitesse verticale - - - + + + A1 - - - + + + A2 - - + + A3 - - + + A4 - - + + FAS - + Cells Velm - + Calculated Calculé - + Add Addition - + Average Moyenne - - + + Min - - + + Max - + Multiply Multiplication - + Totalise - + Cell Element LiPo - + Consumption Consommation - + Distance - + Lowest Min - + Cell %1 Elém. %1 - + Highest Max - + Delta - + Formula Formule - - + + Id - + Instance - - - - + + + + Sensor Capteur - - + + Sources - - + + GPS - + Alt. - - + + Blades Pales - + Multi. - + F - + Inst - + Alt Altitude - + Unit Unité - + Prec - + Ratio - + Multi - + A/Offset - + Filter Filtre - + Persist - + Positive - + Log - + Numbers Chiffres - + Bars Barres - + Script - + Filename Nom de fichier - + Error: Unable to open or read file! Erreur: Impossible d'ouvrir ou de lire le fichier! - + Persistent Persistant - + Off - - - - - - + + + + + + None Aucun - + Name Nom - + Countdown Compte à rebours - + Minute call Annonces minutes - - - + + + FM%1 PV%1 - + FM%1%2 PV%1%2 - + FM%1+%2 PV%1+%2 - - + + Weight Ratio - - + + Switch Inter - - + + NoTrim Pas de trim - + No DR/Expo Pas d'expo/DR - + Offset(%1) Décalage(%1) @@ -8904,24 +8926,24 @@ Mixage actif par défaut si non-renseigné. - + Disabled in all flight modes Désactivé pour toutes les phases de vol - + instant immédiat - - - + + + Custom Prédéfini - + Standard @@ -8957,7 +8979,7 @@ Mixage actif par défaut si non-renseigné. Module - + Failsafe Mode Mode Failsafe @@ -8967,241 +8989,251 @@ Mixage actif par défaut si non-renseigné. 1ère voie - + PPM delay Impulsion - + Negative Négative - + Positive - + Polarity Polarité - + Trainer Mode Mode écolage - + PPM Frame Length Longueur de trame PPM - + CH VOIE - + Antenna Antenne - + Option value - + us µs - + Master/Jack Maître/Jack - + Slave/Jack Elève/Jack - + Master/SBUS Module Maître/SBUS module - + Master/CPPM Module Maître/CPPM Module - + Master/SBUS in battery compartment Maître/SBUS dans compartiment batterie - + RF Output Power Puissance RF - + Sub Type Sous-Type - + Master/Bluetooth Maître/Bluetooth - + Slave/Bluetooth Elève/Bluetooth - + Master/Multi Maître/Multi - + Disable Telemetry Désactiver la télémétrie - + Disable Ch. Map Désactiver "Mapping" des VOIES - + Show values in: Afficher les valeurs en: - + % abbreviation for percent - + μs abbreviation for microseconds - + ms - + Receiver 1 Récepteur 1 - - - + + + X - + Receiver 2 Récepteur 2 - + Receiver 3 Récepteur 3 - + WARNING: changing RF Output Power needs RE-BIND ATTENTION: RE-BIND nécessaire pour tout changement de puissance RF - + Channels Nb de voies - + + RX Frequency + Fréquence RX + + + + Hz + + + + Not set Non défini - + Hold Maintien - + Custom Prédéfini - + No Pulses Pas d'impulsions - + Receiver Récepteur - + WARNING: Requires non-certified firmware! ATTENTION: Nécessite un firmware non certifié! - + Registration ID ID d'enregistrement - + Failsafe Positions Positions Failsafe - + Protocol Protocole - + Multi Radio Protocol Protocole Multi - + Receiver No. Récepteur No. - + Output type Type de sortie - + Open Drain - + Push Pull - + Low Power Puissance Réduite @@ -9209,133 +9241,153 @@ Mixage actif par défaut si non-renseigné. ModuleData - + Positive - + Negative Négative - + Trainer Port Port écolage - + Internal Radio System Module HF interne - + External Radio Module Module HF externe - + Extra Radio System Module HF supplémentaire - + Radio System Module HF - + 10mW - 16CH 10mW - 16 VOIES - - + + 100mW - 16CH 100mW - 16 VOIES - + 500mW - 16CH 500mW - 16 VOIES - + Auto <= 1W - 16CH Auto <= 1W - 16 VOIES - - + + 25mW - 8CH 25mW - 8 VOIES - - + + 25mW - 16CH 25mW - 16 VOIES - + 200mW - 16CH (no telemetry) 200mW - 16 VOIES (pas de télémétrie) - + 500mW - 16CH (no telemetry) 500mW - 16 VOIES (pas de télémétrie) - + 100mW - 16CH (no telemetry) 100mW - 16 VOIES (pas de télémétrie) + + + 25 mW + + + + + 100 mW + + + + + 500 mW + + + + + 1 W + + + + + 2 W + + ModulePanel - + Value Valeur - + Hold Maintien - + No Pulse Pas d'impulsion - + Ask Demander - + Internal Interne - + Internal + External Interne + Externe - + External Externe - - Autodetect Format - Format Détection auto - - - + Bind on channel Bind avec VOIE @@ -9425,11 +9477,6 @@ Mixage actif par défaut si non-renseigné. Telemetry Télémétrie - - - Offset - Décalage - @@ -9480,7 +9527,7 @@ Mixage actif par défaut si non-renseigné. - + Name Nom @@ -9551,7 +9598,7 @@ Mixage actif par défaut si non-renseigné. - + Type @@ -9626,165 +9673,118 @@ Mixage actif par défaut si non-renseigné. Fonctions spéciales - + Protocol Protocole - + Low Faible - + Critical Critique - + Telemetry audio Audio télémétrie - + Altimetry Altimétrie - - + + Vario source Source vario - + Vario limits > Limites vario > - + Sink max Chute max - + Sink min Chute min - + Climb min Pompe min - + Climb max Pompe max - + Center silent Silence centrer - + Top Bar Barre de titre de l'écran d'accueil - - + Volts source Source de la tension - + Altitude source Source de l'altitude - - Various - Divers - - - - Serial protocol - Protocole série - - - - FAS offset - Décalage FAS - - - - mAh count - Compteur mAh - - - - Persistent mAh - Mémorisation des mAh - - - - Current source - Source de mesure de courant - - - - Blades - Pales - - - + Parameters Paramètres - + Telemetry Sensors Capteurs Télémétrie - + Telemetry Screens Écrans Télémétrie - + GF%1 FG%1 - + Global Functions Fonctions globales - + Checklist - - - Analogs - Analogiques - - Unit Unité - - Scale - Echelle - - - + RSSI Alarms Alarmes RSSI @@ -9808,13 +9808,13 @@ Mixage actif par défaut si non-renseigné. - Telemetry - Télémetrie + RF power + Puissance HF - Radio output power - Puissance de sortie + Telemetry + Télémetrie @@ -9863,22 +9863,22 @@ Mixage actif par défaut si non-renseigné. OpenTxEepromInterface - + Unknown error Erreur inconnue - + ... plus %1 errors ... plus %1 erreurs - + Cannot write radio settings Impossible d'écrire les paramètres de la radio - + Cannot write model %1 Impossible d'écrire le modèle %1 @@ -10145,25 +10145,20 @@ Mixage actif par défaut si non-renseigné. RadioInterface - + Cannot write file %1: %2. Impossible d'écrire le fichier %1: %2. - - <b><u>WARNING!</u></b><br>This will reset the fuses of %1 to the factory settings.<br>Writing fuses can mess up your radio.<br>Do this only if you are sure they are wrong!<br>Are you sure you want to continue? - <b><u>AVERTISSEMENT !</u></b><br>Ceci réinitialisera les fusibles %1 à leur valeur par défaut.<br>Modifier les fusibles peut entraîner le blocage de votre émetteur.<br>Ne l'effectuer que si vous êtes certain qu'ils sont incorrects !<br>Etes-vous sûr de vouloir continuer ? - - - - + + Could not delete temporary file: %1 Impossible d'effacer le fichier temporaire %1 - + Unable to find radio SD card! Impossible de trouver la carte SD de la radio! @@ -10303,439 +10298,131 @@ E RawSource - - - - + V - - - - + + s - - ft - - - - - - m - - - - - °C - - - - - ° - - - - - % - - - - - - mph - - - - - - km/h - - - - - m/s - - - - - A - - - - - mAh - - - - - W - - - - - g - - - - + TrmR TrmD - + TrmE TrmP - + TrmT TrmG - + TrmA TrmA - + Trm5 - + Trm6 - + TrmH - + TrmV - - + Batt - - + Time Temps - - + Timer1 Chrono 1 - - + Timer2 Chrono 2 - - + Timer3 Chrono 3 - - RSSI Tx - - - - - RSSI Rx - - - - - RAS - - - - - A1 - - - - - A2 - - - - - A3 - - - - - A4 - - - - - Alt - Altitude - - - - Rpm - - - - - Fuel - Carburant - - - - T1 - - - - - T2 - - - - - Speed - Vitesse - - - - Dist - Distance - - - - GPS Alt - Altitude GPS - - - - Cell - Element LiPo - - - - Cells - Velm - - - - Vfas - Vfas - - - - Curr - Courant - - - - Cnsp - Consommation - - - - Powr - Puissance - - - - AccX - - - - - AccY - - - - - AccZ - - - - - Hdg - Cap - - - - VSpd - Vitesse Verticale - - - - AirSpeed - Vitesse Air - - - - dTE - - - - - A1- - - - - - A2- - - - - - A3- - - - - - A4- - - - - - Alt- - - - - - Alt+ - - - - - Rpm+ - - - - - T1+ - - - - - T2+ - - - - - Speed+ - Vit+ - - - - Dist+ - - - - - AirSpeed+ - VitA+ - - - - Cell- - Elem- - - - - Cells- - Velm- - - - - Vfas- - - - - - Curr+ - Cour+ - - - - Powr+ - Puis+ - - - - ACC - - - - - GPS Time - Heure GPS - - - + REa - + REb - - + + ??? - + ---- - + I as in Input E - + LUA%1%2 - + MAX - + CYC%1 - + TR as in Trainer - + SRC @@ -11104,7 +10791,22 @@ E - + + Hertz + + + + + mS + + + + + uS + + + + TELE @@ -11286,87 +10988,92 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo SetupPanel - + Popup menu available Menu contextuel disponible - + Timer %1 Chrono %1 - + THR GAZ - + Profile Settings Paramètres du profil - + SD structure path not specified or invalid Chemin de la structure SD non spécifié ou invalide - + Copy Copier - + Cut Couper - + Paste Coller - + Clear Effacer - + Insert Insérer - + Delete Supprimer - + Move Up Monter - + Move Down Descendre - + Clear All Effacer Tout - + Clear Timer. Are you sure? Effacer le Chrono. Êtes-vous sûr? - + Clear all Timers. Are you sure? Effacer tous les Chronos. Êtes-vous sûr? - + + Cut Timer. Are you sure? + Couper le Chrono. Êtes-vous sûr? + + + Delete Timer. Are you sure? Supprimer le Chrono. Êtes-vous sûr? @@ -12090,62 +11797,62 @@ La valeur par défaut est configurée dans le profil radio sélectionné.Simulateur Radio (%1) - + Could not determine startup data source. Impossible de déterminer les données source. - + Could not load data, possibly wrong format. Impossible de charger les données, mauvais format. - + Data Load Error Erreur de lecture des données - + Invalid startup data provided. Plese specify a proper file/path. Données de démarrage fournies non valides. Veuillez spécifier un fichier/chemin approprié. - + Simulator Startup Error Erreur de démarrage du simulateur - + Error saving data: could open file for writing: '%1' Erreur de sauvegarde des données: impossible d'écrire le fichier '%1' - + Error saving data: could not get data from simulator interface. Erreur de sauvegarde des données: impossible de récupérer les données depuis l'interface de simulation. - + An unexpected error occurred while attempting to save radio data to file '%1'. Une erreur inattendue s'est produite lors de l'enregistrement des données radio dans le fichier '%1'. - + Data Save Error Erreur de sauvegarde des données - + Cannot open joystick, joystick disabled Impossible d'accéder au Joystick, Joystick désactivé - + Radio firmware error: %1 Erreur firmware radio: %1 - + - Flight Mode %1 (#%2) - Phase de Vol %1 (#%2) @@ -12791,11 +12498,6 @@ Trop d'erreurs, abandon. mAmps (mA) Courant (mA) - - - Range - Plage - TelemetryCustomScreen @@ -12805,22 +12507,22 @@ Trop d'erreurs, abandon. Type d'écran personnalisé - + None Aucun - + Numbers Chiffres - + Bars Barres - + Script @@ -12848,107 +12550,112 @@ Trop d'erreurs, abandon. TelemetryPanel - + FrSky S.PORT - + FrSky D - + FrSky D (cable) FrSky D (câble) - + Telemetry screen %1 Ecran de télémesure %1 - + Source - + Low Alarm Alarme basse - + Critical Alarm Alarme critique - + Winged Shadow How High - + Winged Shadow How High (not supported) Winged Shadow How High (non supporté) - + Alti Alt - + Alti+ Alt+ - + VSpeed Vitesse verticale - - - + + + A1 - - - + + + A2 - - + + A3 - - + + A4 - - + + FAS - + Cells Velm - + --- + + + Delete Sensor. Are you sure? + Supprimer le Capteur. Êtes-vous sûr? + TelemetrySensor @@ -13243,67 +12950,92 @@ Trop d'erreurs, abandon. TelemetrySensorPanel - + TELE%1 - + Popup menu available Menu contextuel disponible - + Lowest Min - + Cell %1 Elém. %1 - + Highest Max - + Delta - + Copy Copier - + Cut Couper - + Paste Coller - + Clear Effacer - + + Insert + Insérer + + + + Delete + Supprimer + + + + Move Up + Monter + + + + Move Down + Descendre + + + Clear All Effacer Tout - + + Cut Telemetry Sensor. Are you sure? + Couper le capteur de télémétrie. Êtes-vous sûr? + + + Clear Telemetry Sensor. Are you sure? Effacer le capteur de télémétrie. Êtes-vous sûr? - + Clear all Telemetry Sensors. Are you sure? Effacez tous les capteurs de télémétrie. Êtes-vous sûr? @@ -13695,6 +13427,12 @@ hh:mm:ss Timer %1 Chrono %1 + + + TMR + as in Timer + + TimerEdit @@ -13724,37 +13462,37 @@ Utilisez CTRL + le défilement de la souris ou les touches PAGE HAUT/PAGE BAS po TimerPanel - + Silent Aucun - + Beeps Bips - + Voice Voix - + Haptic Vibreur - + Not persistent Non persistant - + Persistent (flight) Persistant (vol) - + Persistent (manual reset) Persistant (RAZ manuelle) @@ -14309,128 +14047,68 @@ Extra long : bips extra longs. burnConfigDialog - - + Port - - List all available programmers. - Lister tous les programmateurs supportés. - - - - - - + + + The location of the AVRDUDE executable. The location of the AVRDUDE.EXE executable. Chemin d'accès de l'exécutable AVRDUDE. - + DFU-Util Location Chemin de DFU-UTIL - - - + + Use this button to browse and look for the AVRDUDE executable file. Utiliser ce bouton pour parcourir à la recherche du fichier exécutable AVRDUDE.EXE. - - Programmer used for communicating with the controller. -Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer. - Programmateur utilisé pour la communication avec le contrôleur. -Consulter la documentation du programmateur utilisé et celle d'AVRDUDE pour effectuer le choix approprié. - - - - Communication port to the programmer. - - Port de communication pour le programmateur. - - - - - MCU - Processeur - - - + at91sam3s8-9xr - + Alternate device Dispositif alternatif - + Use advanced controls Utiliser les contrôles avancés - - Extra Arguments - Paramètres supplémentaires - - - - Show Help - Aide - - - - - + + Browse... Parcourir... - + DFU-UTIL Configuration Configuration de DFU-UTIL - + SAM-BA Configuration Configuration de SAM-BA - - - + + Select Location Choisir l'emplacement - - List available programmers - Lister les programmateurs supportés - - - - Avrdude help - Aide d'AVRDUDE - - - - <b><u>WARNING!</u></b><br>Normally CPU type is automatically selected according to the chosen firmware.<br>If you change the CPU type the resulting eeprom could be inconsistent. - <b><u>ATTENTION !</u></b><br>Le type de processeur est normalement choisi automatiquement pour le firmware sélectionné.<br>Si vous le changez, l'EEPROM peut être corrompue lors du transfert. - - - - List Available - Affiche Liste - - - - + Extra arguments used in AVRDUDE. This can be used for providing extra information to AVRDUDE. @@ -14440,16 +14118,6 @@ Permet de fournir des informations supplémentaires à AVRDUDE. A n'utiliser qu'en connaissance de cause: il n'y a pas de contrôle d'erreur et votre programmateur pourrait être endommagé. - - - AVRDUDE Location - Emplacement d'AVRDUDE - - - - Show AVRDUDE help - Affiche l'aide d'AVRDUDE - Programmer Configuration @@ -14457,58 +14125,40 @@ A n'utiliser qu'en connaissance de cause: il n'y a pas de contrô Configuration du programmateur - - + Extra arguments that will be passed to AVRDUDE on every call Paramètres complémentaires passés à chaque appel d'AVRDUDE - - AVRDUDE Configuration - Configuration d'AVRDUDE - - - - Location of AVRDUDE executable - Chemin d'accès de l'exécutable AVRDUDE - - - - Programmer - Programmateur - - - - + CPU of your TX CPU de l'émetteur - - + CPU present on your 9x radio Should be m64 for stock radios m2560 for v4.1 boards CPU de l'émetteur. Devrait être m64 pour les cartes d'origine, m2560 pour les cartes Gruvin9x v4.x - + SAM-BA Location Emplacement de SAM-BA - - + + Location of sam-ba executable Emplacement de l'exécutable SAM-BA - + ARM MCU Processeur ARM - + sam-ba serial port Port série de SAM-BA diff --git a/companion/src/wizarddata.cpp b/companion/src/wizarddata.cpp index f544ee4b0..25adaee24 100644 --- a/companion/src/wizarddata.cpp +++ b/companion/src/wizarddata.cpp @@ -61,27 +61,28 @@ void WizMix::maxMixSwitch(char *name, MixData &mix, int channel, int sw, int wei void WizMix::addMix(ModelData &model, Input input, int weight, int channel, int & mixIndex) { if (input != NO_INPUT) { - bool isHorusOrTaranis = IS_ARM(getCurrentBoard()); if (input >= RUDDER_INPUT && input <= AILERONS_INPUT) { MixData & mix = model.mixData[mixIndex++]; mix.destCh = channel+1; - if (isHorusOrTaranis){ + if (IS_SKY9X(getCurrentBoard())) { + mix.srcRaw = RawSource(SOURCE_TYPE_STICK, input-1); + } + else { int channel = settings.getDefaultChannel(input-1); mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, channel); } - else - mix.srcRaw = RawSource(SOURCE_TYPE_STICK, input-1); + mix.weight = weight; } else if (input==FLAPS_INPUT){ // There ought to be some kind of constants for switches somewhere... - maxMixSwitch((char *)"Flaps Up", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SA0 :-SWITCH_ELE , weight); //Taranis-Horus SA-UP, 9X ELE-UP - maxMixSwitch((char *)"Flaps Dn", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SA2 : SWITCH_ELE , -weight); //Taranis-Horus SA-DOWN, 9X ELE-DOWN + maxMixSwitch((char *)"Flaps Up", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? -SWITCH_ELE : SWITCH_SA0, weight); //Taranis-Horus SA-UP, 9X ELE-UP + maxMixSwitch((char *)"Flaps Dn", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? SWITCH_ELE : SWITCH_SA2, -weight); //Taranis-Horus SA-DOWN, 9X ELE-DOWN } else if (input==AIRBRAKES_INPUT){ - maxMixSwitch((char *)"AirbkOff", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SE0 :-SWITCH_RUD , -weight); //Taranis-Horus SE-UP, 9X RUD-UP - maxMixSwitch((char *)"AirbkOn", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SE2 : SWITCH_RUD , weight); //Tatanis-Horus SE-DOWN, 9X RUD-DOWN + maxMixSwitch((char *)"AirbkOff", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? -SWITCH_RUD : SWITCH_SE0, -weight); //Taranis-Horus SE-UP, 9X RUD-UP + maxMixSwitch((char *)"AirbkOn", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? SWITCH_RUD : SWITCH_SE2, weight); //Tatanis-Horus SE-DOWN, 9X RUD-DOWN } } } @@ -120,7 +121,7 @@ WizMix::operator ModelData() mix.srcRaw = SOURCE_TYPE_MAX; mix.weight = -100; mix.swtch.type = SWITCH_TYPE_SWITCH; - mix.swtch.index = IS_ARM(getCurrentBoard()) ? SWITCH_SF0 : SWITCH_THR; + mix.swtch.index = IS_SKY9X(getCurrentBoard()) ? SWITCH_THR : SWITCH_SF0; mix.mltpx = MLTPX_REP; memset(mix.name, 0, sizeof(mix.name)); strncpy(mix.name, "Cut", MIXDATA_NAME_LEN); diff --git a/launchpad/common/rules b/launchpad/common/rules index cf96b0fda..2ee5a0a6c 100755 --- a/launchpad/common/rules +++ b/launchpad/common/rules @@ -15,9 +15,6 @@ STM32_OPTIONS = -DLUA=YES build: mkdir $(BUILDDIR); - cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=9X ../ ; make libsimulator - cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=GRUVIN9X ../ ; make libsimulator - cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=MEGA2560 ../ ; make libsimulator cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=SKY9X ../ ; make libsimulator cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=9XRPRO ../ ; make libsimulator diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/DSM FwdPrg.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/DSM FwdPrg.lua new file mode 100644 index 000000000..c756634d9 --- /dev/null +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/DSM FwdPrg.lua @@ -0,0 +1,557 @@ +local toolName = "TNS|DSM Forward Programming|TNE" + +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + + +--############################################################################### +-- Multi buffer for DSM description +-- Multi_Buffer[0..2]=="DSM" -> Lua script is running +-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent +-- Multi_Buffer[4..9]=6 bytes of TX to RX data +-- Multi_Buffer[10..25]=16 bytes of RX to TX data +-- +-- To start operation: +-- Write 0x00 at address 3 +-- Write 0x00 at address 10 +-- Write "DSM" at address 0..2 +--############################################################################### + +local RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED = 0, 1, 2, 3, 4, 5, 6, 7 +local MENU, LIST_MENU_NOCHANGING, LIST_MENU2, PERCENTAGE_VALUE = 0x1C, 0x6C, 0x4C, 0xC0 +local Phase = RX_VERSION +local Waiting_RX = 0 +local Text = {} +local Retry=100 +local Blink = 0 +local Value_Changed=0 + +local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId=nil, Back=nil, BackId=nil, CurLine=nil, SelLine=nil, EditLine=nil } +local Line = {} +local RX = { Name="", Version="" } + +local function conv_int16(number) + if number >= 0x8000 then + return number - 0x10000 + end + return number +end + +local function Get_Text(index) + out = Text[index] + if out == nil then -- unknown... + out = "Unknown_"..string.format("%X",index) + end + return out +end + +local function DSM_Release() + multiBuffer( 0, 0 ) +end + +local function DSM_Send(...) + local arg = {...} + for i = 1 , #arg do + multiBuffer( 3+i, arg[i]) + end + multiBuffer( 3, 0x70+#arg) +end + +local function Value_Add(dir) + local line=Line[Menu.SelLine] + Speed = getRotEncSpeed() + if Speed == ROTENC_MIDSPEED then + line.Val = line.Val + (5 * dir) + elseif Speed == ROTENC_HIGHSPEED then + line.Val = line.Val + (15 * dir) + else + line.Val = line.Val + dir + end + if line.Val > line.Max then + line.Val = line.Max + elseif line.Val < line.Min then + line.Val = line.Min + end + if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then + Phase = VALUE_CHANGING + Waiting_RX = 0 + end +end + +local function DSM_Menu(event) + local Speed = 0 + if event == EVT_VIRTUAL_NEXT then + if Menu.EditLine == nil then + -- not changing a value + if Menu.SelLine ~= nil then + if Menu.SelLine < 7 then + local num = Menu.SelLine + for i = Menu.SelLine + 1, 6, 1 do + if Line[i].Type ~= nil and Line[i].Next ~= nil then + Menu.SelLine=i + break + end + end + if num == Menu.SelLine then + if Menu.Next ~= 0 then -- Next + Menu.SelLine = 7 + elseif Menu.Prev ~= 0 then -- Prev + Menu.SelLine = 8 + end + end + elseif Menu.Prev ~= 0 then -- Prev + Menu.SelLine = 8 + end + end + else -- need to inc the value + Value_Add(1) + end + elseif event == EVT_VIRTUAL_PREV then + if Menu.EditLine == nil then + if Menu.SelLine ~= nil then + if Menu.SelLine == 8 and Menu.Next ~= 0 then + Menu.SelLine = 7 + elseif Menu.SelLine > 0 then + if Menu.SelLine > 6 then + Menu.SelLine = 7 + end + local num = Menu.SelLine + for i = Menu.SelLine-1, 0, -1 do + if Line[i].Type ~= nil and Line[i].Next ~= nil then + Menu.SelLine=i + break + end + end + if num == Menu.SelLine then -- Back + Menu.SelLine = -1 + end + else + Menu.SelLine = -1 -- Back + end + end + else -- need to dec the value + Value_Add(-1) + end + elseif event == EVT_VIRTUAL_ENTER then + if Menu.SelLine == -1 then -- Back + Menu.Cur = Menu.Back + Menu.Id = Menu.BackId + Menu.SelLine = 0 + Phase = MENU_TITLE + Waiting_RX = 0 + elseif Menu.SelLine == 7 then -- Next + Menu.Cur = Menu.Next + Menu.Id = Menu.NextId + Menu.SelLine = 0 + Phase = MENU_TITLE + Waiting_RX = 0 + elseif Menu.SelLine == 8 then -- Prev + Menu.Cur = Menu.Prev + Menu.Id = Menu.PrevId + Menu.SelLine = 0 + Phase = MENU_TITLE + Waiting_RX = 0 + elseif Menu.SelLine ~= nil and Line[Menu.SelLine].Next ~= nil then + if Line[Menu.SelLine].Type == MENU then -- Next menu exist + Menu.Cur = Line[Menu.SelLine].Next + Menu.Id = Line[Menu.SelLine].NextId + Phase = MENU_TITLE + Waiting_RX = 0 + else + -- value entry + if Menu.EditLine == Menu.SelLine then + Menu.EditLine = nil + Value_Changed = 0 + Phase = VALUE_CHANGED + Waiting_RX = 0 + else + Menu.EditLine = Menu.SelLine + end + end + end + end +end + +local function DSM_Send_Receive() + if Waiting_RX == 0 then + Waiting_RX = 1 + -- Need to send a request + if Phase == RX_VERSION then -- request RX version + DSM_Send(0x11,0x06,0x00,0x14,0x00,0x00) + elseif Phase == WAIT_CMD then -- keep connection open + DSM_Send(0x00,0x04,0x00,0x00) + elseif Phase == MENU_TITLE then -- request menu title + if Menu.Cur == nil then + DSM_Send(0x12,0x06,0x00,0x14,0x00,0x00) -- first menu only + Menu.Cur = 0 + else + DSM_Send(0x16,0x06,Menu.Id,Menu.Cur,0x00,Menu.SelLine) + end + elseif Phase == MENU_LINES then -- request menu lines + if Menu.CurLine == nil then + DSM_Send(0x13,0x04,Menu.Id,Menu.Cur) -- line 0 + elseif Menu.CurLine >= 0x80 then + local last_byte={0x40,0x01,0x02,0x04,0x00,0x00} -- unknown... + DSM_Send(0x20,0x06,Menu.CurLine-0x80,Menu.CurLine-0x80,0x00,last_byte[Menu.CurLine-0x80+1]) -- line X + else + DSM_Send(0x14,0x06,Menu.Id,Menu.Cur,0x00,Menu.CurLine) -- line X + end + elseif Phase == MENU_VALUES then -- request menu values + DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,Menu.CurLine) -- line X + elseif Phase == VALUE_CHANGING then -- send value + local value=Line[Menu.SelLine].Val + if value < 0 then + value = 0x10000 + value + end + DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value + Phase = VALUE_CHANGING_WAIT + elseif Phase == VALUE_CHANGED then -- send value + if Value_Changed == 0 then + local value=Line[Menu.SelLine].Val + if value < 0 then + value = 0x10000 + value + end + DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value + Value_Changed = Value_Changed + 1 + Waiting_RX = 0 + elseif Value_Changed == 1 then + DSM_Send(0x19,0x06,Line[Menu.SelLine].ValId,Menu.SelLine) -- validate + -- Value_Changed = Value_Changed + 1 + -- Waiting_RX = 0 + --elseif Value_Changed == 2 then + -- DSM_Send(0x1B,0x06,0x10,Menu.SelLine) -- validate again? + -- Value_Changed = Value_Changed + 1 + end + elseif Phase == VALUE_CHANGING_WAIT then + DSM_Send(0x1A,0x06,Line[Menu.SelLine].ValId,Menu.SelLine) + end + multiBuffer(10,0x00); + Retry = 50 + elseif multiBuffer(10) == 0x09 then + -- Answer received + --if multiBuffer(11) == 0x00 then -- waiting for commands? + if multiBuffer(11) == 0x01 then -- read version + --ex: 0x09 0x01 0x00 0x15 0x02 0x22 0x01 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + RX.Name = Get_Text(multiBuffer(13)) + RX.Version = multiBuffer(14).."."..multiBuffer(15).."."..multiBuffer(16) + Phase = MENU_TITLE + elseif multiBuffer(11) == 0x02 then -- read menu title + --ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00 + Menu.Cur = multiBuffer(12) + Menu.Id = multiBuffer(13) + Menu.Title = Get_Text(multiBuffer(14)+multiBuffer(15)*256) + Menu.Prev = multiBuffer(16) + Menu.PrevId = multiBuffer(17) + Menu.Next = multiBuffer(18) + Menu.NextId = multiBuffer(19) + Menu.Back = multiBuffer(20) + Menu.BackId = multiBuffer(21) + for i = 0, 6 do -- clear menu + Line[i] = { Menu = nil, Id = nil, Type = nil, Text="", Next = nil, NextId = nil, ValLine = nil, ValId = nil, Min, Max, Def, Val, Unit, Step } + end + Menu.CurLine = nil + if Menu.Next ~= 0 then + Menu.SelLine = 7 -- highlight Next + else + Menu.SelLine = -1 -- highlight Back + end + Blink = 0 + Phase = MENU_LINES + elseif multiBuffer(11) == 0x03 then -- read menu lines + --ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00 + -- Menu Id line Type Text_idx Next V_Id Val_Min Val_Max Val_Def + --ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00 + Menu.CurLine = multiBuffer(14) + local line = Line[Menu.CurLine] + line.Menu = multiBuffer(12) + line.Id = multiBuffer(13) -- not quite sure yet + line.Type = multiBuffer(15) -- not quite sure yet: 1C is text menu only, 4C/6C is text followed by text list, C0 is text followed by percentage value + line.Text = Get_Text(multiBuffer(16)+multiBuffer(17)*256) + if multiBuffer(18) == Menu.Cur then + line.Next = nil + else + line.Next = multiBuffer(18) -- not quite sure yet: 1C=text menu=>next menu, others=>line number of the value + end + if Menu.SelLine == -1 and line.Next ~= nil then -- Auto select first line of the menu + Menu.SelLine = Menu.CurLine + end + line.NextId = multiBuffer(19) -- not quite sure yet + line.ValLine = multiBuffer(18) -- not quite sure yet + line.ValId = multiBuffer(19) -- not quite sure yet + line.Min = conv_int16(multiBuffer(20)+multiBuffer(21)*256) + line.Max = conv_int16(multiBuffer(22)+multiBuffer(23)*256) + line.Def = conv_int16(multiBuffer(24)+multiBuffer(25)*256) + if line.Type == MENU then + -- nothing to do on menu entries + elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_MENU2 then + line.Val = nil --line.Def - line.Min -- use default value not sure if needed + line.Def = line.Min -- pointer to the start of the list in Text + line.Max = line.Max - line.Min -- max index + line.Min = 0 -- min index + else -- default to numerical value + line.Val = nil --line.Def -- use default value not sure if needed + end + if line.Type ~= 0x1C then -- value to follow + line.Text = line.Text..":" + end + Phase = MENU_LINES + elseif multiBuffer(11) == 0x04 then -- read menu values + --ex: 0x09 0x04 0x53 0x10 0x00 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + -- Menu MeId line VaId Value + --ex: 0x09 0x04 0x61 0x10 0x02 0x10 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + Menu.CurLine = multiBuffer(14) + Line[Menu.CurLine].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256) + Phase = MENU_VALUES + elseif multiBuffer(11) == 0x05 then -- unknown... need to get through the lines... + Menu.CurLine = 0x80 + multiBuffer(12) + Phase = MENU_LINES + elseif multiBuffer(11) == 0x00 and Phase == VALUE_CHANGING then + Phase = VALUE_CHANGING_WAIT + end + -- Data processed + Waiting_RX = 0 + multiBuffer(10,0x00) + Retry = 50 + else + Retry = Retry - 1 + if Retry <= 0 then + -- Retry the RX request + Retry = 50 + Waiting_RX = 0 + if Phase ~= RX_VERSION and Phase ~= VALUE_CHANGING_WAIT then + Phase = WAIT_CMD + end + end + end +end + +local function DSM_Display() + lcd.clear() + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "DSM Forward Programming", MENU_TITLE_COLOR) + --Draw RX Menu + if Phase == RX_VERSION then + lcd.drawText(10,50,"No compatible DSM RX...", BLINK) + else + if Menu.Title ~= nil then + local attrib=0; + lcd.drawText(80,32,Menu.Title,MIDSIZE) + for i = 0, 6 do + if i == Menu.SelLine then + attrib = INVERS + else + attrib = 0 + end + if Line[i] ~= nil and Line[i].Type ~= nil then + if Line[i].Type ~= MENU then -- list/value + if Line[i].Val ~= nil then + local text="" + if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU2 then + text = Get_Text(Line[i].Val+Line[i].Def) + elseif Line[i].Type == PERCENTAGE_VALUE then + text = Line[i].Val.." %" + else + text = Line[i].Val + end + if Menu.EditLine == Menu.SelLine then -- blink edited entry + Blink = Blink + 1 + if Blink > 25 then + attrib = 0 + if Blink > 50 then + Blink = 0 + end + end + end + lcd.drawText(240,32+20*(i+2), text, attrib) -- display value + end + attrib = 0 + end + lcd.drawText(10,32+20*(i+2), Line[i].Text, attrib) -- display text + end + end + if Menu.SelLine == -1 then + lcd.drawText(437,32, "Back", INVERS) + else + lcd.drawText(437,32, "Back", 0) + end + lcd.drawRectangle(437-5, 32-2, 47, 25) + if Menu.Next ~= 0 then + if Menu.SelLine == 7 then + lcd.drawText(437,220, "Next",INVERS) + else + lcd.drawText(437,220, "Next") + end + lcd.drawRectangle(437-5, 220-2, 47, 25) + end + if Menu.Prev ~= 0 then + if Menu.SelLine == 8 then + lcd.drawText(5,220, "Prev",INVERS) + else + lcd.drawText(5,220, "Prev") + end + lcd.drawRectangle(5-5, 220-2, 47, 25) + end + end + lcd.drawText(170,252, "RX "..RX.Name.." v"..RX.Version) -- display RX info + end + else + -- --Draw RX Menu on LCD_W=128 + -- if multiBuffer( 4 ) == 0xFF then + -- lcd.drawText(2,17,"No compatible DSM RX...",SMLSIZE) + -- else + -- if Retry_128 ~= 0 then + -- --Intro page + -- Retry_128 = Retry_128 - 1 + -- lcd.drawScreenTitle("DSM Forward Programming",0,0) + -- lcd.drawText(2,17,"Press Prev Page for previous Menu" ,SMLSIZE) + -- else + -- --Menu page + -- for line = 0, 7, 1 do + -- for i = 0, 21-1, 1 do + -- value=multiBuffer( line*21+6+i ) + -- if value > 0x80 then + -- value = value - 0x80 + -- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS) + -- else + -- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE) + -- end + -- end + -- end + -- end + -- end + end +end + +-- Init +local function DSM_Init() + --Set protocol to talk to + multiBuffer( 0, string.byte('D') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('D') then + error("Not enough memory!") + return 2 + end + --Init TX buffer + multiBuffer( 3, 0x00 ) + --Init RX buffer + multiBuffer( 10, 0x00 ) + --Init telemetry + multiBuffer( 0, string.byte('D') ) + multiBuffer( 1, string.byte('S') ) + multiBuffer( 2, string.byte('M') ) + + --Text to be displayed -> need to use a file instead? + --RX names-- + Text[0x0014]="SPM4651T" + Text[0x0015]="AR637T" + --Lists-- + Text[0x0036]="Throttle" + Text[0x0037]="Aileron" + Text[0x0038]="Elevator" + Text[0x0039]="Rudder" + Text[0x003A]="Gear" + for i=1,7 do -- 3B..41 + Text[0x003A+i]="Aux"..i + end + for i=1,8 do -- 41..49 + Text[0x0041+i]="XPlus-"..i + end + Text[0x004A]="Failsafe" + Text[0x004B]="Main Menu" + Text[0x004E]="Position" + Text[0x0050]="Outputs" + --Text[0x005E]="Inhibit" + Text[0x005F]="Hold Last" + Text[0x0060]="Preset" + --Text[0x0061]="Custom" + --Messages-- + Text[0x0090]="Apply" + Text[0x0093]="Complete" + Text[0x0094]="Done" + Text[0x0097]="Factory Reset" + Text[0x009A]="Capture Failsafe Positions" + Text[0x009C]="Custom Failsafe" + Text[0x00A5]="First Time Setup" + Text[0x00F9]="Gyro settings" + Text[0x0100]="Make sure the model has been" + Text[0x0101]="configured, including wing type," + Text[0x0102]="reversing, travel, trimmed, etc." + Text[0x0103]="before continuing setup." + Text[0x0104]="" + Text[0x0105]="" + Text[0x0106]="Any wing type, channel assignment," + Text[0x0107]="subtrim, or servo reversing changes" + Text[0x0108]="require running through initial" + Text[0x0109]="setup again." + Text[0x010A]="" + Text[0x010B]="" + + Text[0x019C]="Enter Receiver Bind Mode" + Text[0x020A]="Restore from Backup" + Text[0x0209]="Save to Backup" + + Text[0x021A]="Set the model level," + Text[0x021B]="and press Continue." + Text[0x021C]="" + Text[0x021D]="" + + Text[0x021F]="Set the model on its nose," + Text[0x0220]="and press Continue. If the" + Text[0x0221]="orientation on the next" + Text[0x0222]="screen is wrong go back" + Text[0x0223]="and try again." + Text[0x0224]="Continue" + Text[0x0229]="Set Orientation Manually" + + Text[0x0227]="Other settings" + Text[0x022B]="WARNING!" + Text[0x022C]="This will reset the" + Text[0x022D]="configuration to factory" + Text[0x022E]="defaults. This does not" + Text[0x022F]="affect the backup config." + Text[0x0230]="" + Text[0x0231]="This will overwrite the" + Text[0x0232]="backup memory with your" + Text[0x0233]="current configuartion." + Text[0x0234]="" + Text[0x0235]="" + Text[0x0236]="This will overwrite the" + Text[0x0237]="current config with" + Text[0x0238]="that which is in" + Text[0x0239]="the backup memory." + Text[0x023A]="" +end + +-- Main +local function DSM_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + DSM_Release() + return 2 + else + DSM_Menu(event) + DSM_Send_Receive() + DSM_Display() + return 0 + end +end + +return { init=DSM_Init, run=DSM_Run } diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky RB30_RB40.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky RB30_RB40.lua new file mode 100644 index 000000000..213faa6cf --- /dev/null +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky RB30_RB40.lua @@ -0,0 +1,464 @@ +--- - ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +----- # # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local version = "v1.01" + +local VALUE = 0 +local COMBO = 1 + +local edit = false +local page = 1 +local current = 1 +local refreshState = 0 +local refreshIndex = 0 +local pageOffset = 0 +local pages = {} +local fields = {} +local modifications = {} +local margin = 1 +local spacing = 8 +local numberPerPage = 7 + +local configFields = { + { "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} }, + { "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} }, + { "VOut1(V)", VALUE, 0xB2, nil, 50, 84}, + { "VOut2(V)", VALUE, 0xB3, nil, 50, 84}, +} + + +local failsafeFields = { + { "CH1 failsafe", VALUE, 0x82, 150, 80, 220}, + { "CH2 failsafe", VALUE, 0x82, 150, 80, 220}, + { "CH3 failsafe", VALUE, 0x83, 150, 80, 220}, + { "CH4 failsafe", VALUE, 0x83, 150, 80, 220}, + { "CH5 failsafe", VALUE, 0x84, 150, 80, 220}, + { "CH6 failsafe", VALUE, 0x84, 150, 80, 220}, + { "CH7 failsafe", VALUE, 0x85, 150, 80, 220}, + { "CH8 failsafe", VALUE, 0x85, 150, 80, 220}, + { "CH9 failsafe", VALUE, 0x86, 150, 80, 220}, + { "CH10 failsafe", VALUE, 0x86, 150, 80, 220}, + { "CH11 failsafe", VALUE, 0x87, 150, 80, 220}, + { "CH12 failsafe", VALUE, 0x87, 150, 80, 220}, + { "CH13 failsafe", VALUE, 0x88, 150, 80, 220}, + { "CH14 failsafe", VALUE, 0x88, 150, 80, 220}, + { "CH15 failsafe", VALUE, 0x89, 150, 80, 220}, + { "CH16 failsafe", VALUE, 0x89, 150, 80, 220}, + { "CH17 failsafe", VALUE, 0x8A, 150, 80, 220}, + { "CH18 failsafe", VALUE, 0x8A, 150, 80, 220}, + { "CH19 failsafe", VALUE, 0x8B, 150, 80, 220}, + { "CH20 failsafe", VALUE, 0x8B, 150, 80, 220}, + { "CH21 failsafe", VALUE, 0x8C, 150, 80, 220}, + { "CH22 failsafe", VALUE, 0x8C, 150, 80, 220}, + { "CH23 failsafe", VALUE, 0x8D, 150, 80, 220}, + { "CH24 failsafe", VALUE, 0x8D, 150, 80, 220}, +} + +local rx1PinMapFields = { + { "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16}, + { "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16}, + { "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16}, + { "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16}, + { "CH5 RX1 map", VALUE, 0x90, 5, 0, 16}, + { "CH6 RX1 map", VALUE, 0x90, 6, 0, 16}, + { "CH7 RX1 map", VALUE, 0x91, 7, 0, 16}, + { "CH8 RX1 map", VALUE, 0x91, 8, 0, 16}, + { "CH9 RX1 map", VALUE, 0x92, 9, 0, 16}, + { "CH10 RX1 map", VALUE, 0x92, 10, 0, 16}, + { "CH11 RX1 map", VALUE, 0x93, 11, 0, 16}, + { "CH12 RX1 map", VALUE, 0x93, 12, 0, 16}, + { "CH13 RX1 map", VALUE, 0x94, 13, 0, 16}, + { "CH14 RX1 map", VALUE, 0x94, 14, 0, 16}, + { "CH15 RX1 map", VALUE, 0x95, 15, 0, 16}, + { "CH16 RX1 map", VALUE, 0x95, 16, 0, 16}, + { "CH17 RX1 map", VALUE, 0x96, 1, 0, 16}, + { "CH18 RX1 map", VALUE, 0x96, 2, 0, 16}, + { "CH19 RX1 map", VALUE, 0x97, 3, 0, 16}, + { "CH20 RX1 map", VALUE, 0x97, 4, 0, 16}, + { "CH21 RX1 map", VALUE, 0x98, 5, 0, 16}, + { "CH22 RX1 map", VALUE, 0x98, 6, 0, 16}, + { "CH23 RX1 map", VALUE, 0x99, 7, 0, 16}, + { "CH24 RX1 map", VALUE, 0x99, 8, 0, 16}, +} + +local rx2PinMapFields = { + { "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16}, + { "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16}, + { "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16}, + { "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16}, + { "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16}, + { "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16}, + { "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16}, + { "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16}, + { "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16}, + { "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16}, + { "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16}, + { "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16}, + { "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16}, + { "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16}, + { "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16}, + { "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16}, + { "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16}, + { "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16}, + { "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16}, + { "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16}, + { "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16}, + { "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16}, + { "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16}, + { "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16}, +} + +local rx3PinMapFields = { + { "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16}, + { "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16}, + { "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16}, + { "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16}, + { "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16}, + { "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16}, + { "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16}, + { "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16}, + { "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16}, + { "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16}, + { "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16}, + { "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16}, + { "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16}, + { "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16}, + { "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16}, + { "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16}, + { "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16}, + { "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16}, + { "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16}, + { "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16}, + { "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16}, + { "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16}, + { "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16}, + { "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16}, +} + + + + +local function drawScreenTitle(title, page, pages) + if math.fmod(math.floor(getTime() / 100), 10) == 0 then + title = version + end + if LCD_W == 480 then + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, title, MENU_TITLE_COLOR) + lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR) + else + lcd.drawScreenTitle(title, page, pages) + end +end + +-- Change display attribute to current field +local function addField(step) + local field = fields[current] + local min, max + if field[2] == VALUE then + min = field[5] + max = field[6] + elseif field[2] == COMBO then + min = 0 + max = #(field[5]) - 1 + end + if page == 2 and step < 0 and field[4] == min then + field[4] = 0 + elseif page == 2 and step > 0 and field[4] == 0 then + field[4] = min + else + if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then + field[4] = field[4] + step + end + end +end + +-- Select the next or previous page +local function selectPage(step) + local pagesNum = #pages + if configFields[1][4] == 1 then + pagesNum = 1 + elseif configFields[2][4] == 1 then + pagesNum = pagesNum - 1 + end + page = 1 + ((page + step - 1 + pagesNum) % pagesNum) + refreshIndex = 0 + pageOffset = 0 +end + +-- Select the next or previous editable field +local function selectField(step) + current = 1 + ((current + step - 1 + #fields) % #fields) + if current > numberPerPage + pageOffset then + pageOffset = current - numberPerPage + elseif current <= pageOffset then + pageOffset = current - 1 + end +end + +local function drawProgressBar() + if LCD_W == 480 then + local width = (300 * refreshIndex) / #fields + lcd.drawRectangle(100, 10, 300, 6) + lcd.drawFilledRectangle(102, 12, width, 2) + else + local width = (60 * refreshIndex) / #fields + lcd.drawRectangle(45, 1, 60, 6) + lcd.drawFilledRectangle(47, 3, width, 2) + end +end + +-- Redraw the current page +local function redrawFieldPage() + lcd.clear() + + local pagesNum = #pages + if configFields[1][4] == 1 then + pagesNum = 1 + elseif configFields[2][4] == 1 then + pagesNum = pagesNum - 1 + end + drawScreenTitle("RB30/RB40", page, pagesNum) + + if refreshIndex < #fields then + drawProgressBar() + end + + for index = 1, numberPerPage, 1 do + local field = fields[pageOffset + index] + if field == nil then + break + end + + local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0 + + lcd.drawText(1, margin + spacing * index, field[1], attr) + + if field[4] == nil then + lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr) + else + if field[2] == VALUE then + if page == 2 then + if field[4] == 0 then + lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr) + else + lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr) + end + else + if field[4] == 0 then + lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr) + else + if field[3] == 0xB2 or field[3] == 0xB3 then + lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1) + else + lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr) + end + end + end + elseif field[2] == COMBO then + if field[4] >= 0 and field[4] < #(field[5]) then + lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr) + end + end + end + end +end + +local function telemetryIdle(field) + return sportTelemetryPush(0x1C, 0x21, 0x0b80, field) +end + +local function telemetryUnIdle(field) + return sportTelemetryPush(0x1C, 0x20, 0x0b80, field) +end + +local function telemetryRead(field) + return sportTelemetryPush(0x1C, 0x30, 0x0b80, field) +end + +local function telemetryWrite(field, value) + return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256) +end + +local telemetryPopTimeout = 0 +local function refreshNext() + if refreshState == 0 then + if #modifications > 0 then + telemetryWrite(modifications[1][1], modifications[1][2]) + modifications[1] = nil + refreshIndex = 0 + refreshState = 0 + elseif refreshIndex < #fields then + local field = fields[refreshIndex + 1] + if page > 1 then + field = fields[refreshIndex + 2] + end + if telemetryRead(field[3]) == true then + refreshState = 1 + telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms + end + end + elseif refreshState == 1 then + local physicalId, primId, dataId, value = sportTelemetryPop() + if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then + local fieldId = value % 256 + local field = fields[refreshIndex + 1] + if fieldId == field[3] then + value = math.floor(value / 256) + if field[2] == COMBO then + fields[refreshIndex + 1][4] = value + else + fields[refreshIndex + 1][4] = value % 256 + if page > 1 then + value = math.floor(value / 256) + fields[refreshIndex + 2][4] = value + end + end + if page > 1 then + refreshIndex = refreshIndex + 2 + else + refreshIndex = refreshIndex + 1 + end + refreshState = 0 + end + elseif getTime() > telemetryPopTimeout then + fields[refreshIndex + 1][4] = nil + if page > 1 then + fields[refreshIndex + 2][4] = nil + refreshIndex = refreshIndex + 2 + else + refreshIndex = refreshIndex + 1 + end + refreshState = 0 + end + end +end + +local function updateField(field) + local value = field[4] + if field[2] == COMBO and #field == 6 then + value = field[6][1 + value] + elseif field[2] == VALUE and #field == 8 then + value = value + field[8] - field[5] + end + + if page > 1 then + if current % 2 == 1 then + value = value + fields[current + 1][4] * 256 + elseif current % 2 == 0 then + value = fields[current - 1][4] + value * 256 + end + end + modifications[#modifications + 1] = { field[3], value } +end + +-- Main +local function runFieldsPage(event) + if event == EVT_VIRTUAL_EXIT then -- exit script + telemetryUnIdle(0x80) + return 2 + elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field + if fields[current][4] ~= nil then + edit = not edit + if edit == false then + updateField(fields[current]) + end + end + elseif edit then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then + addField(1) + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then + addField(-1) + end + else + if event == EVT_VIRTUAL_NEXT then + selectField(1) + elseif event == EVT_VIRTUAL_PREV then + selectField(-1) + end + end + redrawFieldPage() + return 0 +end + +local function runConfigPage(event) + fields = configFields + return runFieldsPage(event) +end + +local function runFailsafePage(event) + fields = failsafeFields + return runFieldsPage(event) +end + +local function runRx1PinMapPage(event) + fields = rx1PinMapFields + return runFieldsPage(event) +end + +local function runRx2PinMapPage(event) + fields = rx2PinMapFields + return runFieldsPage(event) +end + +local function runRx3PinMapPage(event) + fields = rx3PinMapFields + return runFieldsPage(event) +end + +-- Init +local function init() + current, edit, refreshState, refreshIndex = 1, false, 0, 0 + if LCD_W == 480 then + margin = 10 + spacing = 20 + numberPerPage = 12 + end + pages = { + runConfigPage, + runFailsafePage, + runRx1PinMapPage, + runRx2PinMapPage, + runRx3PinMapPage + } + telemetryIdle(0x80) +end + +-- Main +local function run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_NEXT_PAGE then + if edit == false then + selectPage(1) + end + elseif event == EVT_VIRTUAL_PREV_PAGE then + if edit == false then + killEvents(event) + selectPage(-1) + end + end + + local result = pages[page](event) + refreshNext() + + return result +end + +return { init = init, run = run } + diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt index bf61d8ca6..b03b2c860 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt @@ -1,3 +1,47 @@ +24,0,Assan,Std,0,CH5,CH6,CH7,CH8 +14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2 +14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates +14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf +14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video +41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED +42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED +42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol +34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess +13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess +37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8 +37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8 +37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8 +12,0,CX10,Green,1,Flip,Rate +12,1,CX10,Blue,1,Flip,Rate,Pict,Video +12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess +12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video +12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip +12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH +7,0,Devo,8CH,0,CH5,CH6,CH7,CH8 +7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10 +7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +7,3,Devo,6CH,0,CH5,CH6 +7,4,Devo,7CH,0,CH5,CH6,CH7 +33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow +6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH +45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH +45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH +16,0,ESKY,Std,0,Gyro,Pitch +16,1,ESKY,ET4,0,Gyro,Pitch +35,0,ESKY150,4CH,0 +35,1,ESKY150,7CH,0,FMode,Aux6,Aux7 +69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8 1,1,Flysky,V9x9,1,Flip,Light,Pict,Video 1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL @@ -7,15 +51,11 @@ 28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 -53,0,Flyzone,FZ-410,0 -2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess -2,1,Hubsan,H301,0,RTH,Light,Stab,Video -2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes -41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED -60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 -37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8 -37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8 -37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8 +28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 +53,0,Height,5ch,0,Gear +53,1,Height,8ch,0,Gear,Gyro,Flap,Light 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8 @@ -26,78 +66,50 @@ 15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8 15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +15,5,FrSkyX,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8 64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8 64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8 +65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 55,1,FrSkyRX,CloneTX,0 -39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 -39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9 -39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9 -57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 -68,0,Skyartec,Std,0,CH5,CH6,CH7 -7,0,Devo,8CH,0,CH5,CH6,CH7,CH8 -7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10 -7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -7,3,Devo,6CH,0,CH5,CH6 -7,4,Devo,7CH,0,CH5,CH6,CH7 -30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8 -30,1,WK2x01,WK2401,0 -30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro -30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro -30,4,WK2x01,W6HEL,0,Gear,Col,Gyro -30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro -6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9 -24,0,Assan,Std,0,CH5,CH6,CH7,CH8 -14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2 -14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates -14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf -14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop -14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop -59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video -42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED -42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol -34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess -13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess -12,0,CX10,Green,1,Flip,Rate -12,1,CX10,Blue,1,Flip,Rate,Pict,Video -12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess -12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video -12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip -12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH -33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow -45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH -45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH -45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH -16,0,ESKY,Std,0,Gyro,Pitch -16,1,ESKY,ET4,0,Gyro,Pitch -35,0,ESKY150,4CH,0 -35,1,ESKY150,7CH,0,FMode,Aux6,Aux7 +58,0,FX816,P38,1 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib 23,0,FY326,FY326,1,Flip,RTH,HLess,Expert +47,0,GD00x,V1,1,Trim,LED,Rate +47,1,GD00x,V2,1,Trim,LED,Rate 32,0,GW008,FY326,1,Flip 36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1 36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8 -9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim -9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +4,1,Hisky,HK310,0,Aux +39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 +39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9 +39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9 26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib 26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib +57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess +2,1,Hubsan,H301,0,RTH,Light,Stab,Video +2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes +22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +71,0,JJRC345,Std,1,Flip,HLess,RTH +49,0,KF606,Std,1,Trim +9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate @@ -111,6 +123,9 @@ 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess 44,0,NCC1701,Std,1,Warp +77,0,OMP,M2,0,THold,IdleUp,6G_3D +60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 +60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8 51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess 66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train 29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal @@ -120,8 +135,15 @@ 31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal 31,2,Q303,CX10D,1,Arm,Flip 31,3,Q303,CX10WD,1,Arm,Flip +72,0,Q90C,Std,0,FMode,VTX+ +74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK 50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 +21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 +19,0,Shenqi,Cycle,1 +68,0,Skyartec,Std,0,CH5,CH6,CH7 11,0,SLT,V1,0,Gear,Pitch 11,1,SLT,V2,0,CH5,CH6,CH7,CH8 11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib @@ -129,11 +151,21 @@ 11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict 10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess 10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess +61,0,Tiger,Std,1,Flip,Light +43,0,Traxxas,6519,0 5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY 5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD -61,0,Tiger,Std,1,Flip,Light -46,0,V911s,Std,1,Calib -46,1,E119,Std,1,Calib +48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn +48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn +46,0,V911s,V911s,1,Calib +46,1,V911s,E119,1,Calib +22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9 +30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8 +30,1,WK2x01,WK2401,0 +30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro +30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro +30,4,WK2x01,W6HEL,0,Gear,Col,Gyro +30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro 62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess @@ -141,17 +173,4 @@ 8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess -65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8 -65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 -56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 -19,0,Shenqi,Cycle,1 -4,1,Hisky,HK310,0,Aux -43,0,Traxxas,6519,0 52,0,ZSX,280,1,Light -48,0,V761,Std,1,Gyro -49,0,KF606,Std,1,Trim -47,0,GD00x,V1,1,Trim,LED,Rate -47,1,GD00x,V2,1,Trim,LED,Rate -58,0,FX816,P38,1 diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua index 42de75e4f..14902b782 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua @@ -249,13 +249,13 @@ local function Multi_Init() --Exceptions on first 4 channels... local stick_names = { "Rud", "Ele", "Thr", "Ail" } - if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX + if ( protocol == 4 and sub_protocol == 1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX stick_names[2] = "n-a" stick_names[4] = "n-a" elseif protocol == 43 then -- Traxxas stick_names[2] = "Aux4" stick_names[4] = "Aux3" - elseif protocol == 48 then -- V761 + elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH stick_names[4] = "n-a" elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816 stick_names[1] = "n-a" @@ -278,6 +278,15 @@ local function Multi_Init() ch_order = math.floor(ch_order/4) channel_names[bitand(ch_order,3)+1] = stick_names[1] end + + --Exceptions on first 4 channels... + if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface + channel_names[1] = "ST" + channel_names[2] = "THR" + channel_names[3] = "CH3" + channel_names[4] = "CH4" + end + --Check MultiChan.txt local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r") if f == nil then return end diff --git a/radio/sdcard/horus/THEMES/Darkblue/t18.bmp b/radio/sdcard/horus/THEMES/Darkblue/t18.bmp new file mode 100755 index 000000000..c1220ca1b Binary files /dev/null and b/radio/sdcard/horus/THEMES/Darkblue/t18.bmp differ diff --git a/radio/sdcard/horus/THEMES/Default/t18.bmp b/radio/sdcard/horus/THEMES/Default/t18.bmp new file mode 100755 index 000000000..c1220ca1b Binary files /dev/null and b/radio/sdcard/horus/THEMES/Default/t18.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/X10.bmp b/radio/sdcard/horus/THEMES/Flexi/X10.bmp new file mode 100755 index 000000000..32a730cde Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/X10.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/X10S.bmp b/radio/sdcard/horus/THEMES/Flexi/X10S.bmp new file mode 100644 index 000000000..221e25ec4 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/X10S.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/asterisk.bmp b/radio/sdcard/horus/THEMES/Flexi/asterisk.bmp new file mode 100644 index 000000000..3dd3cfef4 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/asterisk.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/busy.bmp b/radio/sdcard/horus/THEMES/Flexi/busy.bmp new file mode 100644 index 000000000..8e6a8b7f7 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/busy.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/horus.bmp b/radio/sdcard/horus/THEMES/Flexi/horus.bmp new file mode 100644 index 000000000..98bc631cd Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/horus.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_bg.png b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_bg.png new file mode 100644 index 000000000..715792023 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_bg.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_dot.png b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_dot.png new file mode 100644 index 000000000..6f76965a9 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_dot.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_shadow.png b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_shadow.png new file mode 100644 index 000000000..97bf6c577 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_shadow.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_library.png b/radio/sdcard/horus/THEMES/Flexi/mask_library.png new file mode 100644 index 000000000..237883fc5 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_library.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_model.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_model.png new file mode 100644 index 000000000..9832267b7 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_model.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_radio.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_radio.png new file mode 100644 index 000000000..6d93fbccc Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_radio.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_stats.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_stats.png new file mode 100644 index 000000000..ebd482588 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_stats.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_theme.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_theme.png new file mode 100644 index 000000000..3a9fc15e7 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_theme.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_curves.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_curves.png new file mode 100644 index 000000000..6e1e19e8e Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_curves.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_flight_modes.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_flight_modes.png new file mode 100644 index 000000000..e963f0abb Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_flight_modes.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_gvars.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_gvars.png new file mode 100644 index 000000000..0b5015dac Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_gvars.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_heli.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_heli.png new file mode 100644 index 000000000..ecd93d2ff Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_heli.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_inputs.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_inputs.png new file mode 100644 index 000000000..720099c47 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_inputs.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_logical_switches.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_logical_switches.png new file mode 100644 index 000000000..5cd1e3834 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_logical_switches.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_lua_scripts.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_lua_scripts.png new file mode 100644 index 000000000..a20c1ccbd Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_lua_scripts.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_mixer.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_mixer.png new file mode 100644 index 000000000..009b360f1 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_mixer.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_outputs.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_outputs.png new file mode 100644 index 000000000..a209ae8d3 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_outputs.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_setup.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_setup.png new file mode 100644 index 000000000..afe526c8f Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_setup.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_special_functions.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_special_functions.png new file mode 100644 index 000000000..a12a2a50d Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_special_functions.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_telemetry.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_telemetry.png new file mode 100644 index 000000000..d95d3b25f Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_telemetry.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor.png new file mode 100644 index 000000000..68ddd4516 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels1.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels1.png new file mode 100644 index 000000000..b886fc1bc Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels1.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels2.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels2.png new file mode 100644 index 000000000..4d0354e25 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels2.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels3.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels3.png new file mode 100644 index 000000000..d9ba27de7 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels3.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels4.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels4.png new file mode 100644 index 000000000..fb321151f Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels4.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_gvars.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_gvars.png new file mode 100644 index 000000000..55b488d1e Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_gvars.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_inver.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_inver.png new file mode 100644 index 000000000..64f251238 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_inver.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_lockch.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_lockch.png new file mode 100644 index 000000000..360923a09 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_lockch.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_logsw.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_logsw.png new file mode 100644 index 000000000..dc6355143 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_logsw.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes1.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes1.png new file mode 100644 index 000000000..7b0c71f60 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes1.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes2.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes2.png new file mode 100644 index 000000000..f8c04780e Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes2.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_mplex_add.png b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_add.png new file mode 100644 index 000000000..14f4ecc23 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_add.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_mplex_multi.png b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_multi.png new file mode 100644 index 000000000..bcf79695f Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_multi.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_mplex_replace.png b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_replace.png new file mode 100644 index 000000000..faccba0ea Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_replace.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_opentx.png b/radio/sdcard/horus/THEMES/Flexi/mask_opentx.png new file mode 100644 index 000000000..df2b0b356 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_opentx.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_opentx_testmode.png b/radio/sdcard/horus/THEMES/Flexi/mask_opentx_testmode.png new file mode 100644 index 000000000..b535cf8ee Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_opentx_testmode.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_calibration.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_calibration.png new file mode 100644 index 000000000..db696778b Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_calibration.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_global_functions.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_global_functions.png new file mode 100644 index 000000000..3b3efefb5 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_global_functions.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_hardware.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_hardware.png new file mode 100644 index 000000000..f51a1aee1 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_hardware.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_sd_browser.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_sd_browser.png new file mode 100644 index 000000000..75b6a9296 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_sd_browser.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_setup.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_setup.png new file mode 100644 index 000000000..0010a06ab Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_setup.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_spectrum_analyser.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_spectrum_analyser.png new file mode 100755 index 000000000..2908833ec Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_spectrum_analyser.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_tools.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_tools.png new file mode 100755 index 000000000..711d499de Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_tools.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_trainer.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_trainer.png new file mode 100644 index 000000000..7a0b56970 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_trainer.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_version.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_version.png new file mode 100644 index 000000000..8730f6c1a Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_version.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_sbar_mixer.png b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_mixer.png new file mode 100644 index 000000000..154406419 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_mixer.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_sbar_output.png b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_output.png new file mode 100644 index 000000000..12d599823 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_output.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_sbar_to.png b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_to.png new file mode 100644 index 000000000..813610307 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_to.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_analogs.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_analogs.png new file mode 100644 index 000000000..96fc0c8a2 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_analogs.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_debug.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_debug.png new file mode 100644 index 000000000..0dce13d46 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_debug.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_lua.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_lua.png new file mode 100644 index 000000000..d1b54a4d6 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_lua.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_throttle_graph.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_throttle_graph.png new file mode 100644 index 000000000..a3720a005 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_throttle_graph.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_timers.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_timers.png new file mode 100644 index 000000000..78bf00064 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_timers.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_value.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_value.png new file mode 100644 index 000000000..180f16e8c Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_value.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_switches.png b/radio/sdcard/horus/THEMES/Flexi/mask_switches.png new file mode 100644 index 000000000..4097ed751 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_switches.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_curve.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_curve.png new file mode 100644 index 000000000..050229393 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_curve.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_delay.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delay.png new file mode 100644 index 000000000..9b771a94a Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delay.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_delayslow.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delayslow.png new file mode 100644 index 000000000..de2f7d1f7 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delayslow.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_fm.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_fm.png new file mode 100644 index 000000000..b9a2c4a32 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_fm.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_label.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_label.png new file mode 100644 index 000000000..8be12e39b Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_label.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_slow.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_slow.png new file mode 100644 index 000000000..1afbea37d Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_slow.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_switch.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_switch.png new file mode 100644 index 000000000..7c7d646e4 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_switch.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_add_view.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_add_view.png new file mode 100644 index 000000000..7e240372f Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_add_view.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_setup.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_setup.png new file mode 100644 index 000000000..2a39d1e40 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_setup.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view1.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view1.png new file mode 100644 index 000000000..9e67515ec Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view1.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view2.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view2.png new file mode 100644 index 000000000..45cec234d Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view2.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view3.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view3.png new file mode 100644 index 000000000..e5a776b06 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view3.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view4.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view4.png new file mode 100644 index 000000000..9064b9403 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view4.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view5.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view5.png new file mode 100644 index 000000000..724bcc141 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view5.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view6.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view6.png new file mode 100644 index 000000000..2aa43514b Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view6.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view7.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view7.png new file mode 100644 index 000000000..d6a0540f5 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view7.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view8.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view8.png new file mode 100644 index 000000000..82dfd7875 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view8.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat1.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat1.png new file mode 100644 index 000000000..a9335c4bc Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat1.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat2.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat2.png new file mode 100644 index 000000000..e3c899d18 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat2.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_default.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_default.png new file mode 100644 index 000000000..6f3042c67 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_default.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_favorites.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_favorites.png new file mode 100644 index 000000000..e4a37dacb Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_favorites.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane1.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane1.png new file mode 100644 index 000000000..a49a50271 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane1.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane2.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane2.png new file mode 100644 index 000000000..8305b4150 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane2.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane3.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane3.png new file mode 100644 index 000000000..d998144b2 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane3.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_iconback.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_iconback.png new file mode 100644 index 000000000..966f6b7f2 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_iconback.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelname.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelname.png new file mode 100644 index 000000000..2edca73ea Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelname.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelqty.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelqty.png new file mode 100644 index 000000000..9a38e4f13 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelqty.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveback.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveback.png new file mode 100644 index 000000000..63f56df92 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveback.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveico.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveico.png new file mode 100644 index 000000000..3662b9bb0 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveico.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_sdfree.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_sdfree.png new file mode 100644 index 000000000..f0ae81982 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_sdfree.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/question.bmp b/radio/sdcard/horus/THEMES/Flexi/question.bmp new file mode 100644 index 000000000..101d7ed53 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/question.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/shutdown.bmp b/radio/sdcard/horus/THEMES/Flexi/shutdown.bmp new file mode 100755 index 000000000..be7034db7 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/shutdown.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/stick_background.png b/radio/sdcard/horus/THEMES/Flexi/stick_background.png new file mode 100644 index 000000000..9f6d53d92 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/stick_background.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/stick_pointer.png b/radio/sdcard/horus/THEMES/Flexi/stick_pointer.png new file mode 100644 index 000000000..0d75765f9 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/stick_pointer.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/t16.bmp b/radio/sdcard/horus/THEMES/Flexi/t16.bmp new file mode 100755 index 000000000..9c78cb498 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/t16.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/t18.bmp b/radio/sdcard/horus/THEMES/Flexi/t18.bmp new file mode 100755 index 000000000..c1220ca1b Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/t18.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/thumb.bmp b/radio/sdcard/horus/THEMES/Flexi/thumb.bmp new file mode 100644 index 000000000..c0494a694 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/thumb.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/topleft.png b/radio/sdcard/horus/THEMES/Flexi/topleft.png new file mode 100644 index 000000000..603bfe1cf Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/topleft.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/topmenu_opentx.bmp b/radio/sdcard/horus/THEMES/Flexi/topmenu_opentx.bmp new file mode 100644 index 000000000..cbc7f8149 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/topmenu_opentx.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/trackp_background.png b/radio/sdcard/horus/THEMES/Flexi/trackp_background.png new file mode 100644 index 000000000..5beada59e Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/trackp_background.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/tx16s.bmp b/radio/sdcard/horus/THEMES/Flexi/tx16s.bmp new file mode 100644 index 000000000..bb44eda41 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/tx16s.bmp differ diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/background.png b/radio/sdcard/horus/THEMES/Flexi/wizard/background.png new file mode 100644 index 000000000..6b31b2914 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/background.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/itembg.png b/radio/sdcard/horus/THEMES/Flexi/wizard/itembg.png new file mode 100644 index 000000000..b899446b2 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/itembg.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/pgdn.png b/radio/sdcard/horus/THEMES/Flexi/wizard/pgdn.png new file mode 100644 index 000000000..6a1377620 Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/pgdn.png differ diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/pgup.png b/radio/sdcard/horus/THEMES/Flexi/wizard/pgup.png new file mode 100644 index 000000000..06fab5cac Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/pgup.png differ diff --git a/radio/sdcard/horus/WIDGETS/Ghost/img/background.png b/radio/sdcard/horus/WIDGETS/Ghost/img/background.png new file mode 100644 index 000000000..887c022fa Binary files /dev/null and b/radio/sdcard/horus/WIDGETS/Ghost/img/background.png differ diff --git a/radio/sdcard/horus/WIDGETS/Ghost/main.lua b/radio/sdcard/horus/WIDGETS/Ghost/main.lua new file mode 100644 index 000000000..dfaef17c9 --- /dev/null +++ b/radio/sdcard/horus/WIDGETS/Ghost/main.lua @@ -0,0 +1,88 @@ +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local backgroundBitmap +local offsetX +local offsetY +local sensors = {} + +local options = { + { "VTX", BOOL, 0 }, +} + +local function getValues(wgt) + if wgt.options.VTX == 0 then + sensors[1] = string.format("%s", getValue("RFMD")) + sensors[2] = string.format("%d Hz", getValue("FRat")) + sensors[3] = string.format("%d %%", getValue("RQly")) + if (getValue("TPWR") == 0) then + sensors[4] = "Range" + else + sensors[4] = string.format("%d mW", getValue("TPWR")) + end + else + sensors[1] = string.format("%s", getValue("VBan")) + sensors[2] = string.format("%dMHz", getValue("VFrq")) + sensors[3] = string.format("CH: %d", getValue("VChn")) + sensors[4] = string.format("%d mW", getValue("VPwr")) + end +end + +local function create(zone, options) + local wgt = { zone=zone, options=options} + backgroundBitmap = Bitmap.open("/WIDGETS/Ghost/img/background.png") + offsetX = (wgt.zone.w - 178) / 2 + offsetY = (wgt.zone.h - 148) / 2 + return wgt +end + +local function update(wgt, options) + wgt.options = options +end + +local function background(wgt) +end + +function refresh(wgt) + -- runs onty on large enough zone + if wgt.zone.w < 180 or wgt.zone.h < 145 then + return + end + + if backgroundBitmap ~= nil then + lcd.drawBitmap(backgroundBitmap, wgt.zone.x + offsetX, wgt.zone.y + offsetY) + end + + if getRSSI() ~= 0 then + getValues(wgt) + + -- RF Mode/Band + lcd.drawText(wgt.zone.x + offsetX + 75, wgt.zone.y + offsetY + 2, sensors[1], CENTER + DBLSIZE) + + -- Frame rate / Frequency + lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 35, sensors[2], CENTER + DBLSIZE) + + -- RSSI / Channel + lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 70, sensors[3], CENTER + DBLSIZE) + + -- Transmit power + lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 105, sensors[4], CENTER + DBLSIZE) + end + +end + +return { name="Ghost", options=options, create=create, update=update, refresh=refresh, background=background } \ No newline at end of file diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky RB30_RB40.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky RB30_RB40.lua new file mode 100644 index 000000000..213faa6cf --- /dev/null +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky RB30_RB40.lua @@ -0,0 +1,464 @@ +--- - ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +----- # # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local version = "v1.01" + +local VALUE = 0 +local COMBO = 1 + +local edit = false +local page = 1 +local current = 1 +local refreshState = 0 +local refreshIndex = 0 +local pageOffset = 0 +local pages = {} +local fields = {} +local modifications = {} +local margin = 1 +local spacing = 8 +local numberPerPage = 7 + +local configFields = { + { "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} }, + { "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} }, + { "VOut1(V)", VALUE, 0xB2, nil, 50, 84}, + { "VOut2(V)", VALUE, 0xB3, nil, 50, 84}, +} + + +local failsafeFields = { + { "CH1 failsafe", VALUE, 0x82, 150, 80, 220}, + { "CH2 failsafe", VALUE, 0x82, 150, 80, 220}, + { "CH3 failsafe", VALUE, 0x83, 150, 80, 220}, + { "CH4 failsafe", VALUE, 0x83, 150, 80, 220}, + { "CH5 failsafe", VALUE, 0x84, 150, 80, 220}, + { "CH6 failsafe", VALUE, 0x84, 150, 80, 220}, + { "CH7 failsafe", VALUE, 0x85, 150, 80, 220}, + { "CH8 failsafe", VALUE, 0x85, 150, 80, 220}, + { "CH9 failsafe", VALUE, 0x86, 150, 80, 220}, + { "CH10 failsafe", VALUE, 0x86, 150, 80, 220}, + { "CH11 failsafe", VALUE, 0x87, 150, 80, 220}, + { "CH12 failsafe", VALUE, 0x87, 150, 80, 220}, + { "CH13 failsafe", VALUE, 0x88, 150, 80, 220}, + { "CH14 failsafe", VALUE, 0x88, 150, 80, 220}, + { "CH15 failsafe", VALUE, 0x89, 150, 80, 220}, + { "CH16 failsafe", VALUE, 0x89, 150, 80, 220}, + { "CH17 failsafe", VALUE, 0x8A, 150, 80, 220}, + { "CH18 failsafe", VALUE, 0x8A, 150, 80, 220}, + { "CH19 failsafe", VALUE, 0x8B, 150, 80, 220}, + { "CH20 failsafe", VALUE, 0x8B, 150, 80, 220}, + { "CH21 failsafe", VALUE, 0x8C, 150, 80, 220}, + { "CH22 failsafe", VALUE, 0x8C, 150, 80, 220}, + { "CH23 failsafe", VALUE, 0x8D, 150, 80, 220}, + { "CH24 failsafe", VALUE, 0x8D, 150, 80, 220}, +} + +local rx1PinMapFields = { + { "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16}, + { "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16}, + { "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16}, + { "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16}, + { "CH5 RX1 map", VALUE, 0x90, 5, 0, 16}, + { "CH6 RX1 map", VALUE, 0x90, 6, 0, 16}, + { "CH7 RX1 map", VALUE, 0x91, 7, 0, 16}, + { "CH8 RX1 map", VALUE, 0x91, 8, 0, 16}, + { "CH9 RX1 map", VALUE, 0x92, 9, 0, 16}, + { "CH10 RX1 map", VALUE, 0x92, 10, 0, 16}, + { "CH11 RX1 map", VALUE, 0x93, 11, 0, 16}, + { "CH12 RX1 map", VALUE, 0x93, 12, 0, 16}, + { "CH13 RX1 map", VALUE, 0x94, 13, 0, 16}, + { "CH14 RX1 map", VALUE, 0x94, 14, 0, 16}, + { "CH15 RX1 map", VALUE, 0x95, 15, 0, 16}, + { "CH16 RX1 map", VALUE, 0x95, 16, 0, 16}, + { "CH17 RX1 map", VALUE, 0x96, 1, 0, 16}, + { "CH18 RX1 map", VALUE, 0x96, 2, 0, 16}, + { "CH19 RX1 map", VALUE, 0x97, 3, 0, 16}, + { "CH20 RX1 map", VALUE, 0x97, 4, 0, 16}, + { "CH21 RX1 map", VALUE, 0x98, 5, 0, 16}, + { "CH22 RX1 map", VALUE, 0x98, 6, 0, 16}, + { "CH23 RX1 map", VALUE, 0x99, 7, 0, 16}, + { "CH24 RX1 map", VALUE, 0x99, 8, 0, 16}, +} + +local rx2PinMapFields = { + { "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16}, + { "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16}, + { "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16}, + { "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16}, + { "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16}, + { "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16}, + { "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16}, + { "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16}, + { "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16}, + { "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16}, + { "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16}, + { "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16}, + { "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16}, + { "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16}, + { "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16}, + { "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16}, + { "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16}, + { "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16}, + { "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16}, + { "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16}, + { "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16}, + { "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16}, + { "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16}, + { "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16}, +} + +local rx3PinMapFields = { + { "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16}, + { "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16}, + { "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16}, + { "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16}, + { "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16}, + { "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16}, + { "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16}, + { "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16}, + { "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16}, + { "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16}, + { "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16}, + { "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16}, + { "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16}, + { "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16}, + { "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16}, + { "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16}, + { "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16}, + { "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16}, + { "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16}, + { "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16}, + { "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16}, + { "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16}, + { "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16}, + { "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16}, +} + + + + +local function drawScreenTitle(title, page, pages) + if math.fmod(math.floor(getTime() / 100), 10) == 0 then + title = version + end + if LCD_W == 480 then + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, title, MENU_TITLE_COLOR) + lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR) + else + lcd.drawScreenTitle(title, page, pages) + end +end + +-- Change display attribute to current field +local function addField(step) + local field = fields[current] + local min, max + if field[2] == VALUE then + min = field[5] + max = field[6] + elseif field[2] == COMBO then + min = 0 + max = #(field[5]) - 1 + end + if page == 2 and step < 0 and field[4] == min then + field[4] = 0 + elseif page == 2 and step > 0 and field[4] == 0 then + field[4] = min + else + if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then + field[4] = field[4] + step + end + end +end + +-- Select the next or previous page +local function selectPage(step) + local pagesNum = #pages + if configFields[1][4] == 1 then + pagesNum = 1 + elseif configFields[2][4] == 1 then + pagesNum = pagesNum - 1 + end + page = 1 + ((page + step - 1 + pagesNum) % pagesNum) + refreshIndex = 0 + pageOffset = 0 +end + +-- Select the next or previous editable field +local function selectField(step) + current = 1 + ((current + step - 1 + #fields) % #fields) + if current > numberPerPage + pageOffset then + pageOffset = current - numberPerPage + elseif current <= pageOffset then + pageOffset = current - 1 + end +end + +local function drawProgressBar() + if LCD_W == 480 then + local width = (300 * refreshIndex) / #fields + lcd.drawRectangle(100, 10, 300, 6) + lcd.drawFilledRectangle(102, 12, width, 2) + else + local width = (60 * refreshIndex) / #fields + lcd.drawRectangle(45, 1, 60, 6) + lcd.drawFilledRectangle(47, 3, width, 2) + end +end + +-- Redraw the current page +local function redrawFieldPage() + lcd.clear() + + local pagesNum = #pages + if configFields[1][4] == 1 then + pagesNum = 1 + elseif configFields[2][4] == 1 then + pagesNum = pagesNum - 1 + end + drawScreenTitle("RB30/RB40", page, pagesNum) + + if refreshIndex < #fields then + drawProgressBar() + end + + for index = 1, numberPerPage, 1 do + local field = fields[pageOffset + index] + if field == nil then + break + end + + local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0 + + lcd.drawText(1, margin + spacing * index, field[1], attr) + + if field[4] == nil then + lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr) + else + if field[2] == VALUE then + if page == 2 then + if field[4] == 0 then + lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr) + else + lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr) + end + else + if field[4] == 0 then + lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr) + else + if field[3] == 0xB2 or field[3] == 0xB3 then + lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1) + else + lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr) + end + end + end + elseif field[2] == COMBO then + if field[4] >= 0 and field[4] < #(field[5]) then + lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr) + end + end + end + end +end + +local function telemetryIdle(field) + return sportTelemetryPush(0x1C, 0x21, 0x0b80, field) +end + +local function telemetryUnIdle(field) + return sportTelemetryPush(0x1C, 0x20, 0x0b80, field) +end + +local function telemetryRead(field) + return sportTelemetryPush(0x1C, 0x30, 0x0b80, field) +end + +local function telemetryWrite(field, value) + return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256) +end + +local telemetryPopTimeout = 0 +local function refreshNext() + if refreshState == 0 then + if #modifications > 0 then + telemetryWrite(modifications[1][1], modifications[1][2]) + modifications[1] = nil + refreshIndex = 0 + refreshState = 0 + elseif refreshIndex < #fields then + local field = fields[refreshIndex + 1] + if page > 1 then + field = fields[refreshIndex + 2] + end + if telemetryRead(field[3]) == true then + refreshState = 1 + telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms + end + end + elseif refreshState == 1 then + local physicalId, primId, dataId, value = sportTelemetryPop() + if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then + local fieldId = value % 256 + local field = fields[refreshIndex + 1] + if fieldId == field[3] then + value = math.floor(value / 256) + if field[2] == COMBO then + fields[refreshIndex + 1][4] = value + else + fields[refreshIndex + 1][4] = value % 256 + if page > 1 then + value = math.floor(value / 256) + fields[refreshIndex + 2][4] = value + end + end + if page > 1 then + refreshIndex = refreshIndex + 2 + else + refreshIndex = refreshIndex + 1 + end + refreshState = 0 + end + elseif getTime() > telemetryPopTimeout then + fields[refreshIndex + 1][4] = nil + if page > 1 then + fields[refreshIndex + 2][4] = nil + refreshIndex = refreshIndex + 2 + else + refreshIndex = refreshIndex + 1 + end + refreshState = 0 + end + end +end + +local function updateField(field) + local value = field[4] + if field[2] == COMBO and #field == 6 then + value = field[6][1 + value] + elseif field[2] == VALUE and #field == 8 then + value = value + field[8] - field[5] + end + + if page > 1 then + if current % 2 == 1 then + value = value + fields[current + 1][4] * 256 + elseif current % 2 == 0 then + value = fields[current - 1][4] + value * 256 + end + end + modifications[#modifications + 1] = { field[3], value } +end + +-- Main +local function runFieldsPage(event) + if event == EVT_VIRTUAL_EXIT then -- exit script + telemetryUnIdle(0x80) + return 2 + elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field + if fields[current][4] ~= nil then + edit = not edit + if edit == false then + updateField(fields[current]) + end + end + elseif edit then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then + addField(1) + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then + addField(-1) + end + else + if event == EVT_VIRTUAL_NEXT then + selectField(1) + elseif event == EVT_VIRTUAL_PREV then + selectField(-1) + end + end + redrawFieldPage() + return 0 +end + +local function runConfigPage(event) + fields = configFields + return runFieldsPage(event) +end + +local function runFailsafePage(event) + fields = failsafeFields + return runFieldsPage(event) +end + +local function runRx1PinMapPage(event) + fields = rx1PinMapFields + return runFieldsPage(event) +end + +local function runRx2PinMapPage(event) + fields = rx2PinMapFields + return runFieldsPage(event) +end + +local function runRx3PinMapPage(event) + fields = rx3PinMapFields + return runFieldsPage(event) +end + +-- Init +local function init() + current, edit, refreshState, refreshIndex = 1, false, 0, 0 + if LCD_W == 480 then + margin = 10 + spacing = 20 + numberPerPage = 12 + end + pages = { + runConfigPage, + runFailsafePage, + runRx1PinMapPage, + runRx2PinMapPage, + runRx3PinMapPage + } + telemetryIdle(0x80) +end + +-- Main +local function run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_NEXT_PAGE then + if edit == false then + selectPage(1) + end + elseif event == EVT_VIRTUAL_PREV_PAGE then + if edit == false then + killEvents(event) + selectPage(-1) + end + end + + local result = pages[page](event) + refreshNext() + + return result +end + +return { init = init, run = run } + diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt index bf61d8ca6..b03b2c860 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt @@ -1,3 +1,47 @@ +24,0,Assan,Std,0,CH5,CH6,CH7,CH8 +14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2 +14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates +14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf +14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video +41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED +42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED +42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol +34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess +13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess +37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8 +37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8 +37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8 +12,0,CX10,Green,1,Flip,Rate +12,1,CX10,Blue,1,Flip,Rate,Pict,Video +12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess +12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video +12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip +12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH +7,0,Devo,8CH,0,CH5,CH6,CH7,CH8 +7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10 +7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +7,3,Devo,6CH,0,CH5,CH6 +7,4,Devo,7CH,0,CH5,CH6,CH7 +33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow +6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH +45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH +45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH +16,0,ESKY,Std,0,Gyro,Pitch +16,1,ESKY,ET4,0,Gyro,Pitch +35,0,ESKY150,4CH,0 +35,1,ESKY150,7CH,0,FMode,Aux6,Aux7 +69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8 1,1,Flysky,V9x9,1,Flip,Light,Pict,Video 1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL @@ -7,15 +51,11 @@ 28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 -53,0,Flyzone,FZ-410,0 -2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess -2,1,Hubsan,H301,0,RTH,Light,Stab,Video -2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes -41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED -60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 -37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8 -37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8 -37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8 +28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 +53,0,Height,5ch,0,Gear +53,1,Height,8ch,0,Gear,Gyro,Flap,Light 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8 @@ -26,78 +66,50 @@ 15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8 15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +15,5,FrSkyX,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8 64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8 64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8 +65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 55,1,FrSkyRX,CloneTX,0 -39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 -39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9 -39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9 -57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 -68,0,Skyartec,Std,0,CH5,CH6,CH7 -7,0,Devo,8CH,0,CH5,CH6,CH7,CH8 -7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10 -7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -7,3,Devo,6CH,0,CH5,CH6 -7,4,Devo,7CH,0,CH5,CH6,CH7 -30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8 -30,1,WK2x01,WK2401,0 -30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro -30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro -30,4,WK2x01,W6HEL,0,Gear,Col,Gyro -30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro -6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9 -24,0,Assan,Std,0,CH5,CH6,CH7,CH8 -14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2 -14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates -14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf -14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop -14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop -59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video -42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED -42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol -34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess -13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess -12,0,CX10,Green,1,Flip,Rate -12,1,CX10,Blue,1,Flip,Rate,Pict,Video -12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess -12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video -12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip -12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH -33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow -45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH -45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH -45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH -16,0,ESKY,Std,0,Gyro,Pitch -16,1,ESKY,ET4,0,Gyro,Pitch -35,0,ESKY150,4CH,0 -35,1,ESKY150,7CH,0,FMode,Aux6,Aux7 +58,0,FX816,P38,1 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib 23,0,FY326,FY326,1,Flip,RTH,HLess,Expert +47,0,GD00x,V1,1,Trim,LED,Rate +47,1,GD00x,V2,1,Trim,LED,Rate 32,0,GW008,FY326,1,Flip 36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1 36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8 -9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim -9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +4,1,Hisky,HK310,0,Aux +39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 +39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9 +39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9 26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib 26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib +57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess +2,1,Hubsan,H301,0,RTH,Light,Stab,Video +2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes +22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +71,0,JJRC345,Std,1,Flip,HLess,RTH +49,0,KF606,Std,1,Trim +9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate @@ -111,6 +123,9 @@ 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess 44,0,NCC1701,Std,1,Warp +77,0,OMP,M2,0,THold,IdleUp,6G_3D +60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 +60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8 51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess 66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train 29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal @@ -120,8 +135,15 @@ 31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal 31,2,Q303,CX10D,1,Arm,Flip 31,3,Q303,CX10WD,1,Arm,Flip +72,0,Q90C,Std,0,FMode,VTX+ +74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK 50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 +21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 +19,0,Shenqi,Cycle,1 +68,0,Skyartec,Std,0,CH5,CH6,CH7 11,0,SLT,V1,0,Gear,Pitch 11,1,SLT,V2,0,CH5,CH6,CH7,CH8 11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib @@ -129,11 +151,21 @@ 11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict 10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess 10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess +61,0,Tiger,Std,1,Flip,Light +43,0,Traxxas,6519,0 5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY 5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD -61,0,Tiger,Std,1,Flip,Light -46,0,V911s,Std,1,Calib -46,1,E119,Std,1,Calib +48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn +48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn +46,0,V911s,V911s,1,Calib +46,1,V911s,E119,1,Calib +22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9 +30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8 +30,1,WK2x01,WK2401,0 +30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro +30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro +30,4,WK2x01,W6HEL,0,Gear,Col,Gyro +30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro 62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess @@ -141,17 +173,4 @@ 8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess -65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8 -65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 -56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 -19,0,Shenqi,Cycle,1 -4,1,Hisky,HK310,0,Aux -43,0,Traxxas,6519,0 52,0,ZSX,280,1,Light -48,0,V761,Std,1,Gyro -49,0,KF606,Std,1,Trim -47,0,GD00x,V1,1,Trim,LED,Rate -47,1,GD00x,V2,1,Trim,LED,Rate -58,0,FX816,P38,1 diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua index 42de75e4f..14902b782 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua @@ -249,13 +249,13 @@ local function Multi_Init() --Exceptions on first 4 channels... local stick_names = { "Rud", "Ele", "Thr", "Ail" } - if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX + if ( protocol == 4 and sub_protocol == 1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX stick_names[2] = "n-a" stick_names[4] = "n-a" elseif protocol == 43 then -- Traxxas stick_names[2] = "Aux4" stick_names[4] = "Aux3" - elseif protocol == 48 then -- V761 + elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH stick_names[4] = "n-a" elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816 stick_names[1] = "n-a" @@ -278,6 +278,15 @@ local function Multi_Init() ch_order = math.floor(ch_order/4) channel_names[bitand(ch_order,3)+1] = stick_names[1] end + + --Exceptions on first 4 channels... + if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface + channel_names[1] = "ST" + channel_names[2] = "THR" + channel_names[3] = "CH3" + channel_names[4] = "CH4" + end + --Check MultiChan.txt local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r") if f == nil then return end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua index bcd9238f4..9cf7fdefd 100755 --- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua @@ -52,10 +52,10 @@ end local function fieldIncDec(event, value, max, force) if edit or force==true then - if event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REPT then + if event == EVT_VIRTUAL_INC then value = (value + max) dirty = true - elseif event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + elseif event == EVT_VIRTUAL_DEC then value = (value + max + 2) dirty = true end @@ -93,11 +93,11 @@ local function navigate(event, fieldMax, prevPage, nextPage) dirty = blinkChanged() end else - if event == EVT_VIRTUAL_NEXT then + if event == EVT_VIRTUAL_NEXT_PAGE then page = nextPage field = 0 dirty = true - elseif event == EVT_VIRTUAL_PREV then + elseif event == EVT_VIRTUAL_PREV_PAGE then page = prevPage field = 0 killEvents(event); @@ -335,7 +335,7 @@ local function drawConfirmationMenu() if rudderMode == 1 then drawNextLine(x, y, "Rudder", rudCH1) end - lcd.drawText(48, LCD_H-8, "[Enter Long] to confirm", 0); + lcd.drawText(0, LCD_H-8, "[Enter Long] to confirm", 0); lcd.drawFilledRectangle(0, LCD_H-9, LCD_W, 9, 0) fieldsMax = 0 end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua index 321b7324f..923acc43b 100755 --- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua @@ -99,11 +99,11 @@ local function navigate(event, fieldMax, prevPage, nextPage) dirty = blinkChanged() end else - if event == EVT_PAGE_BREAK or event == EVT_RIGHT_FIRST then + if event == EVT_VIRTUAL_NEXT_PAGE then page = nextPage field = 0 dirty = true - elseif event == EVT_PAGE_LONG or event == EVT_LEFT_FIRST then + elseif event == EVT_VIRTUAL_PREV_PAGE then page = prevPage field = 0 killEvents(event); diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua index 26282cdf7..d52c1f936 100755 --- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua @@ -103,11 +103,11 @@ local function navigate(event, fieldMax, prevPage, nextPage) dirty = blinkChanged() end else - if event == EVT_PAGE_BREAK or event==EVT_RIGHT_BREAK then + if event == EVT_VIRTUAL_NEXT_PAGE then page = nextPage field = 0 dirty = true - elseif event == EVT_PAGE_LONG or event==EVT_LEFT_BREAK then + elseif event == EVT_VIRTUAL_PREV_PAGE then page = prevPage field = 0 killEvents(event); diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky RB30_RB40.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky RB30_RB40.lua new file mode 100644 index 000000000..213faa6cf --- /dev/null +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky RB30_RB40.lua @@ -0,0 +1,464 @@ +--- - ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +----- # # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local version = "v1.01" + +local VALUE = 0 +local COMBO = 1 + +local edit = false +local page = 1 +local current = 1 +local refreshState = 0 +local refreshIndex = 0 +local pageOffset = 0 +local pages = {} +local fields = {} +local modifications = {} +local margin = 1 +local spacing = 8 +local numberPerPage = 7 + +local configFields = { + { "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} }, + { "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} }, + { "VOut1(V)", VALUE, 0xB2, nil, 50, 84}, + { "VOut2(V)", VALUE, 0xB3, nil, 50, 84}, +} + + +local failsafeFields = { + { "CH1 failsafe", VALUE, 0x82, 150, 80, 220}, + { "CH2 failsafe", VALUE, 0x82, 150, 80, 220}, + { "CH3 failsafe", VALUE, 0x83, 150, 80, 220}, + { "CH4 failsafe", VALUE, 0x83, 150, 80, 220}, + { "CH5 failsafe", VALUE, 0x84, 150, 80, 220}, + { "CH6 failsafe", VALUE, 0x84, 150, 80, 220}, + { "CH7 failsafe", VALUE, 0x85, 150, 80, 220}, + { "CH8 failsafe", VALUE, 0x85, 150, 80, 220}, + { "CH9 failsafe", VALUE, 0x86, 150, 80, 220}, + { "CH10 failsafe", VALUE, 0x86, 150, 80, 220}, + { "CH11 failsafe", VALUE, 0x87, 150, 80, 220}, + { "CH12 failsafe", VALUE, 0x87, 150, 80, 220}, + { "CH13 failsafe", VALUE, 0x88, 150, 80, 220}, + { "CH14 failsafe", VALUE, 0x88, 150, 80, 220}, + { "CH15 failsafe", VALUE, 0x89, 150, 80, 220}, + { "CH16 failsafe", VALUE, 0x89, 150, 80, 220}, + { "CH17 failsafe", VALUE, 0x8A, 150, 80, 220}, + { "CH18 failsafe", VALUE, 0x8A, 150, 80, 220}, + { "CH19 failsafe", VALUE, 0x8B, 150, 80, 220}, + { "CH20 failsafe", VALUE, 0x8B, 150, 80, 220}, + { "CH21 failsafe", VALUE, 0x8C, 150, 80, 220}, + { "CH22 failsafe", VALUE, 0x8C, 150, 80, 220}, + { "CH23 failsafe", VALUE, 0x8D, 150, 80, 220}, + { "CH24 failsafe", VALUE, 0x8D, 150, 80, 220}, +} + +local rx1PinMapFields = { + { "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16}, + { "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16}, + { "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16}, + { "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16}, + { "CH5 RX1 map", VALUE, 0x90, 5, 0, 16}, + { "CH6 RX1 map", VALUE, 0x90, 6, 0, 16}, + { "CH7 RX1 map", VALUE, 0x91, 7, 0, 16}, + { "CH8 RX1 map", VALUE, 0x91, 8, 0, 16}, + { "CH9 RX1 map", VALUE, 0x92, 9, 0, 16}, + { "CH10 RX1 map", VALUE, 0x92, 10, 0, 16}, + { "CH11 RX1 map", VALUE, 0x93, 11, 0, 16}, + { "CH12 RX1 map", VALUE, 0x93, 12, 0, 16}, + { "CH13 RX1 map", VALUE, 0x94, 13, 0, 16}, + { "CH14 RX1 map", VALUE, 0x94, 14, 0, 16}, + { "CH15 RX1 map", VALUE, 0x95, 15, 0, 16}, + { "CH16 RX1 map", VALUE, 0x95, 16, 0, 16}, + { "CH17 RX1 map", VALUE, 0x96, 1, 0, 16}, + { "CH18 RX1 map", VALUE, 0x96, 2, 0, 16}, + { "CH19 RX1 map", VALUE, 0x97, 3, 0, 16}, + { "CH20 RX1 map", VALUE, 0x97, 4, 0, 16}, + { "CH21 RX1 map", VALUE, 0x98, 5, 0, 16}, + { "CH22 RX1 map", VALUE, 0x98, 6, 0, 16}, + { "CH23 RX1 map", VALUE, 0x99, 7, 0, 16}, + { "CH24 RX1 map", VALUE, 0x99, 8, 0, 16}, +} + +local rx2PinMapFields = { + { "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16}, + { "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16}, + { "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16}, + { "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16}, + { "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16}, + { "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16}, + { "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16}, + { "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16}, + { "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16}, + { "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16}, + { "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16}, + { "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16}, + { "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16}, + { "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16}, + { "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16}, + { "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16}, + { "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16}, + { "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16}, + { "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16}, + { "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16}, + { "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16}, + { "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16}, + { "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16}, + { "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16}, +} + +local rx3PinMapFields = { + { "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16}, + { "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16}, + { "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16}, + { "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16}, + { "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16}, + { "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16}, + { "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16}, + { "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16}, + { "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16}, + { "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16}, + { "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16}, + { "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16}, + { "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16}, + { "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16}, + { "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16}, + { "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16}, + { "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16}, + { "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16}, + { "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16}, + { "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16}, + { "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16}, + { "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16}, + { "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16}, + { "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16}, +} + + + + +local function drawScreenTitle(title, page, pages) + if math.fmod(math.floor(getTime() / 100), 10) == 0 then + title = version + end + if LCD_W == 480 then + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, title, MENU_TITLE_COLOR) + lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR) + else + lcd.drawScreenTitle(title, page, pages) + end +end + +-- Change display attribute to current field +local function addField(step) + local field = fields[current] + local min, max + if field[2] == VALUE then + min = field[5] + max = field[6] + elseif field[2] == COMBO then + min = 0 + max = #(field[5]) - 1 + end + if page == 2 and step < 0 and field[4] == min then + field[4] = 0 + elseif page == 2 and step > 0 and field[4] == 0 then + field[4] = min + else + if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then + field[4] = field[4] + step + end + end +end + +-- Select the next or previous page +local function selectPage(step) + local pagesNum = #pages + if configFields[1][4] == 1 then + pagesNum = 1 + elseif configFields[2][4] == 1 then + pagesNum = pagesNum - 1 + end + page = 1 + ((page + step - 1 + pagesNum) % pagesNum) + refreshIndex = 0 + pageOffset = 0 +end + +-- Select the next or previous editable field +local function selectField(step) + current = 1 + ((current + step - 1 + #fields) % #fields) + if current > numberPerPage + pageOffset then + pageOffset = current - numberPerPage + elseif current <= pageOffset then + pageOffset = current - 1 + end +end + +local function drawProgressBar() + if LCD_W == 480 then + local width = (300 * refreshIndex) / #fields + lcd.drawRectangle(100, 10, 300, 6) + lcd.drawFilledRectangle(102, 12, width, 2) + else + local width = (60 * refreshIndex) / #fields + lcd.drawRectangle(45, 1, 60, 6) + lcd.drawFilledRectangle(47, 3, width, 2) + end +end + +-- Redraw the current page +local function redrawFieldPage() + lcd.clear() + + local pagesNum = #pages + if configFields[1][4] == 1 then + pagesNum = 1 + elseif configFields[2][4] == 1 then + pagesNum = pagesNum - 1 + end + drawScreenTitle("RB30/RB40", page, pagesNum) + + if refreshIndex < #fields then + drawProgressBar() + end + + for index = 1, numberPerPage, 1 do + local field = fields[pageOffset + index] + if field == nil then + break + end + + local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0 + + lcd.drawText(1, margin + spacing * index, field[1], attr) + + if field[4] == nil then + lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr) + else + if field[2] == VALUE then + if page == 2 then + if field[4] == 0 then + lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr) + else + lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr) + end + else + if field[4] == 0 then + lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr) + else + if field[3] == 0xB2 or field[3] == 0xB3 then + lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1) + else + lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr) + end + end + end + elseif field[2] == COMBO then + if field[4] >= 0 and field[4] < #(field[5]) then + lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr) + end + end + end + end +end + +local function telemetryIdle(field) + return sportTelemetryPush(0x1C, 0x21, 0x0b80, field) +end + +local function telemetryUnIdle(field) + return sportTelemetryPush(0x1C, 0x20, 0x0b80, field) +end + +local function telemetryRead(field) + return sportTelemetryPush(0x1C, 0x30, 0x0b80, field) +end + +local function telemetryWrite(field, value) + return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256) +end + +local telemetryPopTimeout = 0 +local function refreshNext() + if refreshState == 0 then + if #modifications > 0 then + telemetryWrite(modifications[1][1], modifications[1][2]) + modifications[1] = nil + refreshIndex = 0 + refreshState = 0 + elseif refreshIndex < #fields then + local field = fields[refreshIndex + 1] + if page > 1 then + field = fields[refreshIndex + 2] + end + if telemetryRead(field[3]) == true then + refreshState = 1 + telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms + end + end + elseif refreshState == 1 then + local physicalId, primId, dataId, value = sportTelemetryPop() + if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then + local fieldId = value % 256 + local field = fields[refreshIndex + 1] + if fieldId == field[3] then + value = math.floor(value / 256) + if field[2] == COMBO then + fields[refreshIndex + 1][4] = value + else + fields[refreshIndex + 1][4] = value % 256 + if page > 1 then + value = math.floor(value / 256) + fields[refreshIndex + 2][4] = value + end + end + if page > 1 then + refreshIndex = refreshIndex + 2 + else + refreshIndex = refreshIndex + 1 + end + refreshState = 0 + end + elseif getTime() > telemetryPopTimeout then + fields[refreshIndex + 1][4] = nil + if page > 1 then + fields[refreshIndex + 2][4] = nil + refreshIndex = refreshIndex + 2 + else + refreshIndex = refreshIndex + 1 + end + refreshState = 0 + end + end +end + +local function updateField(field) + local value = field[4] + if field[2] == COMBO and #field == 6 then + value = field[6][1 + value] + elseif field[2] == VALUE and #field == 8 then + value = value + field[8] - field[5] + end + + if page > 1 then + if current % 2 == 1 then + value = value + fields[current + 1][4] * 256 + elseif current % 2 == 0 then + value = fields[current - 1][4] + value * 256 + end + end + modifications[#modifications + 1] = { field[3], value } +end + +-- Main +local function runFieldsPage(event) + if event == EVT_VIRTUAL_EXIT then -- exit script + telemetryUnIdle(0x80) + return 2 + elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field + if fields[current][4] ~= nil then + edit = not edit + if edit == false then + updateField(fields[current]) + end + end + elseif edit then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then + addField(1) + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then + addField(-1) + end + else + if event == EVT_VIRTUAL_NEXT then + selectField(1) + elseif event == EVT_VIRTUAL_PREV then + selectField(-1) + end + end + redrawFieldPage() + return 0 +end + +local function runConfigPage(event) + fields = configFields + return runFieldsPage(event) +end + +local function runFailsafePage(event) + fields = failsafeFields + return runFieldsPage(event) +end + +local function runRx1PinMapPage(event) + fields = rx1PinMapFields + return runFieldsPage(event) +end + +local function runRx2PinMapPage(event) + fields = rx2PinMapFields + return runFieldsPage(event) +end + +local function runRx3PinMapPage(event) + fields = rx3PinMapFields + return runFieldsPage(event) +end + +-- Init +local function init() + current, edit, refreshState, refreshIndex = 1, false, 0, 0 + if LCD_W == 480 then + margin = 10 + spacing = 20 + numberPerPage = 12 + end + pages = { + runConfigPage, + runFailsafePage, + runRx1PinMapPage, + runRx2PinMapPage, + runRx3PinMapPage + } + telemetryIdle(0x80) +end + +-- Main +local function run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_NEXT_PAGE then + if edit == false then + selectPage(1) + end + elseif event == EVT_VIRTUAL_PREV_PAGE then + if edit == false then + killEvents(event) + selectPage(-1) + end + end + + local result = pages[page](event) + refreshNext() + + return result +end + +return { init = init, run = run } + diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt index bf61d8ca6..b03b2c860 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt @@ -1,3 +1,47 @@ +24,0,Assan,Std,0,CH5,CH6,CH7,CH8 +14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2 +14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates +14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf +14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop +59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video +41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED +42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED +42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol +34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess +13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess +37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8 +37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8 +37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8 +12,0,CX10,Green,1,Flip,Rate +12,1,CX10,Blue,1,Flip,Rate,Pict,Video +12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess +12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video +12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip +12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH +7,0,Devo,8CH,0,CH5,CH6,CH7,CH8 +7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10 +7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +7,3,Devo,6CH,0,CH5,CH6 +7,4,Devo,7CH,0,CH5,CH6,CH7 +33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow +6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill +70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH +45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH +45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH +16,0,ESKY,Std,0,Gyro,Pitch +16,1,ESKY,ET4,0,Gyro,Pitch +35,0,ESKY150,4CH,0 +35,1,ESKY150,7CH,0,FMode,Aux6,Aux7 +69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8 1,1,Flysky,V9x9,1,Flip,Light,Pict,Video 1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL @@ -7,15 +51,11 @@ 28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 -53,0,Flyzone,FZ-410,0 -2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess -2,1,Hubsan,H301,0,RTH,Light,Stab,Video -2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes -41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED -60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 -37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8 -37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8 -37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8 +28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 +53,0,Height,5ch,0,Gear +53,1,Height,8ch,0,Gear,Gyro,Flap,Light 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8 @@ -26,78 +66,50 @@ 15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8 15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +15,5,FrSkyX,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8 64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8 64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8 +65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 55,1,FrSkyRX,CloneTX,0 -39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 -39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9 -39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9 -57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 -68,0,Skyartec,Std,0,CH5,CH6,CH7 -7,0,Devo,8CH,0,CH5,CH6,CH7,CH8 -7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10 -7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -7,3,Devo,6CH,0,CH5,CH6 -7,4,Devo,7CH,0,CH5,CH6,CH7 -30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8 -30,1,WK2x01,WK2401,0 -30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro -30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro -30,4,WK2x01,W6HEL,0,Gear,Col,Gyro -30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro -6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill -22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9 -24,0,Assan,Std,0,CH5,CH6,CH7,CH8 -14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2 -14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates -14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf -14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop -14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop -59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video -42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED -42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol -34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess -13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess -12,0,CX10,Green,1,Flip,Rate -12,1,CX10,Blue,1,Flip,Rate,Pict,Video -12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess -12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video -12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip -12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH -33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow -45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH -45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH -45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH -16,0,ESKY,Std,0,Gyro,Pitch -16,1,ESKY,ET4,0,Gyro,Pitch -35,0,ESKY150,4CH,0 -35,1,ESKY150,7CH,0,FMode,Aux6,Aux7 +58,0,FX816,P38,1 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib 23,0,FY326,FY326,1,Flip,RTH,HLess,Expert +47,0,GD00x,V1,1,Trim,LED,Rate +47,1,GD00x,V2,1,Trim,LED,Rate 32,0,GW008,FY326,1,Flip 36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1 36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal 4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8 -9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim -9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +4,1,Hisky,HK310,0,Aux +39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 +39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9 +39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9 26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib 26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib +57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess +2,1,Hubsan,H301,0,RTH,Light,Stab,Video +2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes +22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +71,0,JJRC345,Std,1,Flip,HLess,RTH +49,0,KF606,Std,1,Trim +9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim +73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate @@ -111,6 +123,9 @@ 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess 44,0,NCC1701,Std,1,Warp +77,0,OMP,M2,0,THold,IdleUp,6G_3D +60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 +60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8 51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess 66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train 29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal @@ -120,8 +135,15 @@ 31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal 31,2,Q303,CX10D,1,Arm,Flip 31,3,Q303,CX10WD,1,Arm,Flip +72,0,Q90C,Std,0,FMode,VTX+ +74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK 50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 +21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 +19,0,Shenqi,Cycle,1 +68,0,Skyartec,Std,0,CH5,CH6,CH7 11,0,SLT,V1,0,Gear,Pitch 11,1,SLT,V2,0,CH5,CH6,CH7,CH8 11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib @@ -129,11 +151,21 @@ 11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict 10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess 10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess +61,0,Tiger,Std,1,Flip,Light +43,0,Traxxas,6519,0 5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY 5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD -61,0,Tiger,Std,1,Flip,Light -46,0,V911s,Std,1,Calib -46,1,E119,Std,1,Calib +48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn +48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn +46,0,V911s,V911s,1,Calib +46,1,V911s,E119,1,Calib +22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9 +30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8 +30,1,WK2x01,WK2401,0 +30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro +30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro +30,4,WK2x01,W6HEL,0,Gear,Col,Gyro +30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro 62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess @@ -141,17 +173,4 @@ 8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess -65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 -65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8 -65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 -56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 -19,0,Shenqi,Cycle,1 -4,1,Hisky,HK310,0,Aux -43,0,Traxxas,6519,0 52,0,ZSX,280,1,Light -48,0,V761,Std,1,Gyro -49,0,KF606,Std,1,Trim -47,0,GD00x,V1,1,Trim,LED,Rate -47,1,GD00x,V2,1,Trim,LED,Rate -58,0,FX816,P38,1 diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua index 42de75e4f..14902b782 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua @@ -249,13 +249,13 @@ local function Multi_Init() --Exceptions on first 4 channels... local stick_names = { "Rud", "Ele", "Thr", "Ail" } - if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX + if ( protocol == 4 and sub_protocol == 1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX stick_names[2] = "n-a" stick_names[4] = "n-a" elseif protocol == 43 then -- Traxxas stick_names[2] = "Aux4" stick_names[4] = "Aux3" - elseif protocol == 48 then -- V761 + elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH stick_names[4] = "n-a" elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816 stick_names[1] = "n-a" @@ -278,6 +278,15 @@ local function Multi_Init() ch_order = math.floor(ch_order/4) channel_names[bitand(ch_order,3)+1] = stick_names[1] end + + --Exceptions on first 4 channels... + if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface + channel_names[1] = "ST" + channel_names[2] = "THR" + channel_names[3] = "CH3" + channel_names[4] = "CH4" + end + --Check MultiChan.txt local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r") if f == nil then return end diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 972a805a1..03ec58003 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -53,6 +53,7 @@ option(MODULE_PROTOCOL_FLEX "Add support for non certified FLEX modules" OFF) option(MODULE_PROTOCOL_D8 "Add support for D8 modules" ON) option(FRSKY_RELEASE "Used to build FrSky released firmware" OFF) option(TBS_RELEASE "Used to build TBS released firmware" OFF) +option(IMRC_RELEASE "Used to build IMRC released firmware" OFF) option(HARDWARE_TRAINER_MULTI "Allow multi trainer" OFF) option(BOOTLOADER "Include Bootloader" ON) @@ -370,6 +371,10 @@ if(TBS_RELEASE) add_definitions(-DTBS_RELEASE) endif() +if(IMRC_RELEASE) + add_definitions(-DIMRC_RELEASE) +endif() + if(FRSKY_RELEASE) add_definitions(-DFRSKY_RELEASE) set(POPUP_LEVEL 3) diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index be53e8921..ac7294877 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -158,9 +158,9 @@ const char * const unitsFilenames[] = { "ml", "founce", "mlpm", - "spare1", - "spare2", - "spare3", + "hertz", + "ms", + "us", "spare4", "spare5", "spare6", diff --git a/radio/src/crc.cpp b/radio/src/crc.cpp index 26a1af500..c0be4d7fa 100644 --- a/radio/src/crc.cpp +++ b/radio/src/crc.cpp @@ -79,3 +79,48 @@ uint8_t crc8(const uint8_t * ptr, uint32_t len) } return crc; } + +// CRC8 implementation with polynom = 0xBA +const unsigned char crc8tab_BA[256] = { + 0x00, 0xBA, 0xCE, 0x74, 0x26, 0x9C, 0xE8, 0x52, + 0x4C, 0xF6, 0x82, 0x38, 0x6A, 0xD0, 0xA4, 0x1E, + 0x98, 0x22, 0x56, 0xEC, 0xBE, 0x04, 0x70, 0xCA, + 0xD4, 0x6E, 0x1A, 0xA0, 0xF2, 0x48, 0x3C, 0x86, + 0x8A, 0x30, 0x44, 0xFE, 0xAC, 0x16, 0x62, 0xD8, + 0xC6, 0x7C, 0x08, 0xB2, 0xE0, 0x5A, 0x2E, 0x94, + 0x12, 0xA8, 0xDC, 0x66, 0x34, 0x8E, 0xFA, 0x40, + 0x5E, 0xE4, 0x90, 0x2A, 0x78, 0xC2, 0xB6, 0x0C, + 0xAE, 0x14, 0x60, 0xDA, 0x88, 0x32, 0x46, 0xFC, + 0xE2, 0x58, 0x2C, 0x96, 0xC4, 0x7E, 0x0A, 0xB0, + 0x36, 0x8C, 0xF8, 0x42, 0x10, 0xAA, 0xDE, 0x64, + 0x7A, 0xC0, 0xB4, 0x0E, 0x5C, 0xE6, 0x92, 0x28, + 0x24, 0x9E, 0xEA, 0x50, 0x02, 0xB8, 0xCC, 0x76, + 0x68, 0xD2, 0xA6, 0x1C, 0x4E, 0xF4, 0x80, 0x3A, + 0xBC, 0x06, 0x72, 0xC8, 0x9A, 0x20, 0x54, 0xEE, + 0xF0, 0x4A, 0x3E, 0x84, 0xD6, 0x6C, 0x18, 0xA2, + 0xE6, 0x5C, 0x28, 0x92, 0xC0, 0x7A, 0x0E, 0xB4, + 0xAA, 0x10, 0x64, 0xDE, 0x8C, 0x36, 0x42, 0xF8, + 0x7E, 0xC4, 0xB0, 0x0A, 0x58, 0xE2, 0x96, 0x2C, + 0x32, 0x88, 0xFC, 0x46, 0x14, 0xAE, 0xDA, 0x60, + 0x6C, 0xD6, 0xA2, 0x18, 0x4A, 0xF0, 0x84, 0x3E, + 0x20, 0x9A, 0xEE, 0x54, 0x06, 0xBC, 0xC8, 0x72, + 0xF4, 0x4E, 0x3A, 0x80, 0xD2, 0x68, 0x1C, 0xA6, + 0xB8, 0x02, 0x76, 0xCC, 0x9E, 0x24, 0x50, 0xEA, + 0x48, 0xF2, 0x86, 0x3C, 0x6E, 0xD4, 0xA0, 0x1A, + 0x04, 0xBE, 0xCA, 0x70, 0x22, 0x98, 0xEC, 0x56, + 0xD0, 0x6A, 0x1E, 0xA4, 0xF6, 0x4C, 0x38, 0x82, + 0x9C, 0x26, 0x52, 0xE8, 0xBA, 0x00, 0x74, 0xCE, + 0xC2, 0x78, 0x0C, 0xB6, 0xE4, 0x5E, 0x2A, 0x90, + 0x8E, 0x34, 0x40, 0xFA, 0xA8, 0x12, 0x66, 0xDC, + 0x5A, 0xE0, 0x94, 0x2E, 0x7C, 0xC6, 0xB2, 0x08, + 0x16, 0xAC, 0xD8, 0x62, 0x30, 0x8A, 0xFE, 0x44 +}; + +uint8_t crc8_BA(const uint8_t * ptr, uint32_t len) +{ + uint8_t crc = 0; + for (uint32_t i=0; i> 8; } } afhds3)); #endif @@ -617,8 +617,9 @@ PACK(struct ModelData { NOBACKUP(RssiAlarmData rssiAlarms); - NOBACKUP(uint8_t spare1:6 SKIP); - NOBACKUP(uint8_t potsWarnMode:2); + uint8_t spare1:3; + uint8_t thrTrimSw:3; + uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES]; int16_t failsafeChannels[MAX_OUTPUT_CHANNELS]; @@ -637,6 +638,20 @@ PACK(struct ModelData { CUSTOM_SCREENS_DATA char modelRegistrationID[PXX2_LEN_REGISTRATION_ID]; + + + uint8_t getThrottleStickTrimSource() const + { + // The order here is TERA, so that 0 (default) means Throttle + switch (thrTrimSw) { + case 0: + return MIXSRC_TrimThr; + case 2: + return MIXSRC_TrimRud; + default: + return thrTrimSw + MIXSRC_FIRST_TRIM; + } + } }); /* @@ -756,7 +771,8 @@ PACK(struct RadioData { uint8_t backlightMode:3; int8_t antennaMode:2; uint8_t disableRtcWarning:1; - int8_t spare1:2 SKIP; + uint8_t keysBacklight:1; + int8_t spare1:1 SKIP; NOBACKUP(TrainerData trainer); NOBACKUP(uint8_t view); // index of view in main screen NOBACKUP(BUZZER_FIELD); /* 2bits */ diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp index 5b1fb2dae..20de19e9a 100644 --- a/radio/src/functions.cpp +++ b/radio/src/functions.cpp @@ -343,7 +343,7 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext #if defined(VARIO) case FUNC_VARIO: - newActiveFunctions |= (1 << FUNCTION_VARIO); + newActiveFunctions |= (1u << FUNCTION_VARIO); break; #endif @@ -351,15 +351,22 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext #if defined(SDCARD) case FUNC_LOGS: if (CFN_PARAM(cfn)) { - newActiveFunctions |= (1 << FUNCTION_LOGS); + newActiveFunctions |= (1u << FUNCTION_LOGS); logDelay = CFN_PARAM(cfn); } break; #endif case FUNC_BACKLIGHT: - newActiveFunctions |= (1 << FUNCTION_BACKLIGHT); + { + getvalue_t raw = getValue(CFN_PARAM(cfn)); +#if defined(COLORLCD) + requiredBacklightBright = (1024 - raw) * (BACKLIGHT_LEVEL_MAX - BACKLIGHT_LEVEL_MIN) / 2048; +#else + requiredBacklightBright = (1024 - raw) * 100 / 2048; +#endif break; + } case FUNC_SCREENSHOT: if (!(functionsContext.activeSwitches & switch_mask)) { diff --git a/radio/src/globals.h b/radio/src/globals.h index cf67dbc4a..f63dfefe0 100644 --- a/radio/src/globals.h +++ b/radio/src/globals.h @@ -50,6 +50,7 @@ extern uint8_t trimsDisplayMask; extern uint16_t maxMixerDuration; extern uint8_t requiredSpeakerVolume; +extern uint8_t requiredBacklightBright; enum MainRequest { REQUEST_SCREENSHOT, diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h index e7367524f..40773737e 100644 --- a/radio/src/gui/128x64/gui.h +++ b/radio/src/gui/128x64/gui.h @@ -215,6 +215,8 @@ extern int8_t s_copySrcRow; extern int8_t s_copyTgtOfs; extern uint8_t s_currIdx; extern uint8_t s_currIdxSubMenu; +extern uint16_t s_currSrcRaw; +extern uint16_t s_currScale; extern uint8_t s_copySrcIdx; extern uint8_t s_copySrcCh; extern int8_t s_currCh; @@ -274,9 +276,6 @@ uint8_t getMixesCount(); void insertMix(uint8_t idx); void deleteMix(uint8_t idx); -typedef int (*FnFuncP) (int x); -void drawFunction(FnFuncP fn, uint8_t offset=0); - void onSourceLongEnterPress(const char *result); uint8_t switchToMix(uint8_t source); diff --git a/radio/src/gui/128x64/menu_model.cpp b/radio/src/gui/128x64/menu_model.cpp index b6f5b3bb3..b98372bd3 100644 --- a/radio/src/gui/128x64/menu_model.cpp +++ b/radio/src/gui/128x64/menu_model.cpp @@ -46,3 +46,5 @@ void editSingleName(coord_t x, coord_t y, const char * label, char * name, uint8 uint8_t s_currIdx; uint8_t s_currIdxSubMenu; +uint16_t s_currSrcRaw; +uint16_t s_currScale; diff --git a/radio/src/gui/128x64/model_curve_edit.cpp b/radio/src/gui/128x64/model_curve_edit.cpp index 5aa43b05d..dbdc09eb1 100644 --- a/radio/src/gui/128x64/model_curve_edit.cpp +++ b/radio/src/gui/128x64/model_curve_edit.cpp @@ -171,14 +171,18 @@ void menuModelCurveOne(event_t event) killEvents(event); break; #elif defined(NAVIGATION_XLITE) - case EVT_KEY_LONG(KEY_SHIFT): - pushMenu(menuChannelsView); - killEvents(event); + case EVT_KEY_FIRST(KEY_ENTER): + if (IS_SHIFT_PRESSED()) { + pushMenu(menuChannelsView); + killEvents(event); + } break; #endif } - drawCurve(0); + drawCurve(); + if (s_currSrcRaw != MIXSRC_NONE) + drawCursor(applyCurrentCurve); attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); for (uint8_t i=0; i<5+crv.points; i++) { diff --git a/radio/src/gui/128x64/model_display.cpp b/radio/src/gui/128x64/model_display.cpp index 6c5bf2f47..39b8d196a 100644 --- a/radio/src/gui/128x64/model_display.cpp +++ b/radio/src/gui/128x64/model_display.cpp @@ -242,10 +242,10 @@ void menuModelDisplay(event_t event) } break; case 1: - bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS); + bar.barMin = checkIncDec(event, bar.barMin, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); break; case 2: - bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); + bar.barMax = checkIncDec(event, bar.barMax, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); break; } } diff --git a/radio/src/gui/128x64/model_flightmodes.cpp b/radio/src/gui/128x64/model_flightmodes.cpp index 0002bf23b..07f5f0163 100644 --- a/radio/src/gui/128x64/model_flightmodes.cpp +++ b/radio/src/gui/128x64/model_flightmodes.cpp @@ -64,13 +64,8 @@ void menuModelFlightModeOne(event_t event) drawFlightMode(13*FW, 0, s_currIdx+1, (getFlightMode()==s_currIdx ? BOLD : 0)); #if defined(GVARS) && !defined(GVARS_IN_CURVES_SCREEN) -#if defined(PCBTARANIS) #define VERTICAL_SHIFT (ITEM_MODEL_FLIGHT_MODE_FADE_IN-ITEM_MODEL_FLIGHT_MODE_TRIMS) static const uint8_t mstate_tab_fm1[] = {0, 3, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1, 1}; -#else - #define VERTICAL_SHIFT (ITEM_MODEL_FLIGHT_MODE_FADE_IN-ITEM_MODEL_FLIGHT_MODE_SWITCH) - static const uint8_t mstate_tab_fm1[] = {0, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1}; -#endif static const uint8_t mstate_tab_others[] = {0, 0, 3, 0, 0, (uint8_t)-1, 2, 2, 2, 2, 2}; check(event, 0, nullptr, 0, (s_currIdx == 0) ? mstate_tab_fm1 : mstate_tab_others, DIM(mstate_tab_others)-1, ITEM_MODEL_FLIGHT_MODE_MAX - HEADER_LINE - (s_currIdx==0 ? (ITEM_MODEL_FLIGHT_MODE_FADE_IN-ITEM_MODEL_FLIGHT_MODE_SWITCH-1) : 0)); diff --git a/radio/src/gui/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp index 575ce4fb7..077d84cb3 100644 --- a/radio/src/gui/128x64/model_input_edit.cpp +++ b/radio/src/gui/128x64/model_input_edit.cpp @@ -21,7 +21,6 @@ #include "opentx.h" #define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) -#define EXPO_ONE_FM_WIDTH (5*FW) int expoFn(int x) { @@ -31,28 +30,6 @@ int expoFn(int x) return anas[ed->chn]; } -void drawFunction(FnFuncP fn, uint8_t offset) -{ - lcdDrawVerticalLine(CURVE_CENTER_X-offset, 0/*TODO CURVE_CENTER_Y-CURVE_SIDE_WIDTH*/, CURVE_SIDE_WIDTH*2, 0xee); - lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee); - - coord_t prev_yv = (coord_t)-1; - - for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) { - coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX); - if (prev_yv != (coord_t)-1) { - if (abs((int8_t)yv-prev_yv) <= 1) { - lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE); - } - else { - uint8_t tmp = (prev_yv < yv ? 0 : 1); - lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv); - } - } - prev_yv = yv; - } -} - enum ExposFields { EXPO_FIELD_INPUT_NAME, EXPO_FIELD_LINE_NAME, @@ -78,7 +55,7 @@ void menuModelExpoOne(event_t event) killEvents(event); } #elif defined(NAVIGATION_XLITE) - if (event == EVT_KEY_LONG(KEY_SHIFT)) { + if (event == EVT_KEY_FIRST(KEY_ENTER) && IS_SHIFT_PRESSED()) { pushMenu(menuChannelsView); killEvents(event); } @@ -113,13 +90,15 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr); - if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); + if (attr) + ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); break; case EXPO_FIELD_SCALE: lcdDrawTextAlignedLeft(y, STR_SCALE); - drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), attr); - if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); + drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), RIGHT | attr); + if (attr) + ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); break; case EXPO_FIELD_WEIGHT: @@ -159,34 +138,20 @@ void menuModelExpoOne(event_t event) break; case EXPO_FIELD_TRIM: - uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); + uint8_t notStick = (ed->srcRaw > MIXSRC_Ail); int8_t carryTrim = -ed->carryTrim; lcdDrawTextAlignedLeft(y, STR_TRIM); - lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, RIGHT | (menuHorizontalPosition==0 ? attr : 0)); - if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST); + lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (notStick && carryTrim == 0) ? 0 : carryTrim+1, RIGHT | (menuHorizontalPosition==0 ? attr : 0)); + if (attr) + ed->carryTrim = -checkIncDecModel(event, carryTrim, notStick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST); break; } y += FH; } drawFunction(expoFn); - - int x512 = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - drawSensorCustomValue(LCD_W-FW, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); - if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); - } - else { - lcdDrawNumber(LCD_W-FW, 6*FH, calcRESXto1000(x512), RIGHT | PREC1); - } - x512 = limit(-1024, x512, 1024); - int y512 = expoFn(x512); - y512 = limit(-1024, y512, 1024); - lcdDrawNumber(CURVE_CENTER_X-FWNUM, 1*FH, calcRESXto1000(y512), RIGHT | PREC1); - - x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH); - y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; - - lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1); - lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1); + // those parameters are global so that they can be reused in the curve edit screen + s_currSrcRaw = ed->srcRaw; + s_currScale = ed->scale; + drawCursor(expoFn); } diff --git a/radio/src/gui/128x64/model_inputs_mixes.cpp b/radio/src/gui/128x64/model_inputs_mixes.cpp deleted file mode 100644 index 93342bf24..000000000 --- a/radio/src/gui/128x64/model_inputs_mixes.cpp +++ /dev/null @@ -1,849 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "opentx.h" - -#define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) -#define EXPO_ONE_FM_WIDTH (5*FW) - -int expoFn(int x) -{ - ExpoData *ed = expoAddress(s_currIdx); - int16_t anas[MAX_INPUTS] = {0}; - anas[ed->chn] = x; - applyExpos(anas, e_perout_mode_inactive_flight_mode); - return anas[ed->chn]; -} - -void drawFunction(FnFuncP fn, uint8_t offset) -{ - lcdDrawVerticalLine(CURVE_CENTER_X-offset, 0, LCD_H, 0xee); - lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee); - - coord_t prev_yv = (coord_t)-1; - - for (int8_t xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) { - coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX); - if (prev_yv != (coord_t)-1) { - if (abs((int8_t)yv-prev_yv) <= 1) { - lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE); - } - else { - uint8_t tmp = (prev_yv < yv ? 0 : 1); - lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv); - } - } - prev_yv = yv; - } -} - - -uint8_t getExpoMixCount(uint8_t expo) -{ - uint8_t count = 0; - uint8_t ch ; - - for(int8_t i=(expo ? MAX_EXPOS-1 : MAX_MIXERS-1); i>=0; i--) { - ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw); - if (ch != 0) { - count++; - } - } - return count; -} - -bool reachExpoMixCountLimit(uint8_t expo) -{ - // check mixers count limit - if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) { - POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER); - return true; - } - return false; -} - -void deleteExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); - } - else { - MixData *mix = mixAddress(idx); - memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData)); - } - resumeMixerCalculations(); - storageDirty(EE_MODEL); -} - -// TODO avoid this global s_currCh on ARM boards ... -int8_t s_currCh; -void insertExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(expo, sizeof(ExpoData)); - expo->mode = 3; // pos&neg - expo->chn = s_currCh - 1; - expo->weight = 100; - } - else { - MixData *mix = mixAddress(idx); - memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - memclear(mix, sizeof(MixData)); - mix->destCh = s_currCh-1; - mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channelOrder(s_currCh)); - mix->weight = 100; - } - resumeMixerCalculations(); - storageDirty(EE_MODEL); -} - -void copyExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - } - else { - MixData *mix = mixAddress(idx); - memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - } - resumeMixerCalculations(); - storageDirty(EE_MODEL); -} - -bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up) -{ - void *x, *y; - uint8_t size; - int8_t tgt_idx = (up ? idx-1 : idx+1); - - if (expo) { - x = (ExpoData *)expoAddress(idx); - - if (tgt_idx < 0) { - if (((ExpoData *)x)->chn == 0) - return false; - ((ExpoData *)x)->chn--; - return true; - } - - if (tgt_idx == MAX_EXPOS) { - if (((ExpoData *)x)->chn == MAX_INPUTS-1) - return false; - ((ExpoData *)x)->chn++; - return true; - } - - y = (ExpoData *)expoAddress(tgt_idx); - if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) { - if (up) { - if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--; - else return false; - } - else { - if (((ExpoData *)x)->chnchn++; - else return false; - } - return true; - } - - size = sizeof(ExpoData); - } - else { - x = (MixData *)mixAddress(idx); - - if (tgt_idx < 0) { - if (((MixData *)x)->destCh == 0) - return false; - ((MixData *)x)->destCh--; - return true; - } - - if (tgt_idx == MAX_MIXERS) { - if (((MixData *)x)->destCh == MAX_OUTPUT_CHANNELS-1) - return false; - ((MixData *)x)->destCh++; - return true; - } - - y = (MixData *)mixAddress(tgt_idx); - uint8_t destCh = ((MixData *)x)->destCh; - if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) { - if (up) { - if (destCh>0) ((MixData *)x)->destCh--; - else return false; - } - else { - if (destChdestCh++; - else return false; - } - return true; - } - - size = sizeof(MixData); - } - - pauseMixerCalculations(); - memswap(x, y, size); - resumeMixerCalculations(); - - idx = tgt_idx; - return true; -} - -enum ExposFields { - EXPO_FIELD_NAME, - EXPO_FIELD_WEIGHT, - EXPO_FIELD_EXPO, - EXPO_FIELD_CURVE, - CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES) - EXPO_FIELD_SWITCH, - EXPO_FIELD_SIDE, - EXPO_FIELD_MAX -}; - -#define CURVE_ROWS 0 - -void menuModelExpoOne(event_t event) -{ - ExpoData * ed = expoAddress(s_currIdx); - drawSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0); - - SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, CURVE_ROWS, CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); - - int8_t sub = menuVerticalPosition; - - coord_t y = MENU_HEADER_HEIGHT + 1; - - for (uint8_t i=0; i0 ? BLINK|INVERS : INVERS) : 0); - switch (i) { - case EXPO_FIELD_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN-sizeof(ed->name)*FW, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); - break; - - case EXPO_FIELD_WEIGHT: - lcdDrawTextAlignedLeft(y, STR_WEIGHT); - ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, -100, 100, attr, 0, event); - break; - - case EXPO_FIELD_EXPO: - lcdDrawTextAlignedLeft(y, STR_EXPO); - if (ed->curveMode==MODE_EXPO || ed->curveParam==0) { - ed->curveMode = MODE_EXPO; - ed->curveParam = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, 0, event); - } - else { - lcdDrawText(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); - } - break; - - case EXPO_FIELD_CURVE: - lcdDrawTextAlignedLeft(y, STR_CURVE); - if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) { - drawCurveName(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr); - if (attr) { - CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1); - if (ed->curveParam) ed->curveMode = MODE_CURVE; - if (ed->curveParam>=CURVE_BASE && event==EVT_KEY_LONG(KEY_ENTER)) { - s_currIdxSubMenu = ed->curveParam - CURVE_BASE; - pushMenu(menuModelCurveOne); - } - } - } - else { - lcdDrawText(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); - } - break; - -#if defined(FLIGHT_MODES) - case EXPO_FIELD_FLIGHT_MODES: - ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-EXPO_ONE_FM_WIDTH, y, event, ed->flightModes, attr); - break; -#endif - - case EXPO_FIELD_SWITCH: - ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->swtch, attr, event); - break; - - case EXPO_FIELD_SIDE: - ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VCURVEFUNC, 4-ed->mode, 1, 3, attr, event); - break; - } - y += FH; - } - - drawFunction(expoFn); - - int16_t x512 = calibratedAnalogs[ed->chn]; - lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto100(x512), 0); - int16_t y512 = expoFn(x512); - lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0); - - x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH); - y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; - - lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1); - lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1); -} - -enum MixFields { - MIX_FIELD_NAME, - MIX_FIELD_SOURCE, - MIX_FIELD_WEIGHT, - MIX_FIELD_OFFSET, - MIX_FIELD_TRIM, - MIX_FIELD_CURVE, - CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE) - MIX_FIELD_SWITCH, - MIX_FIELD_WARNING, - MIX_FIELD_MLTPX, - MIX_FIELD_DELAY_UP, - MIX_FIELD_DELAY_DOWN, - MIX_FIELD_SLOW_UP, - MIX_FIELD_SLOW_DOWN, - MIX_FIELD_COUNT -}; - -#define GAUGE_WIDTH 33 -#define GAUGE_HEIGHT 6 -void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) -{ - int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); - int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); - int barMin = offset - weight; - int barMax = offset + weight; - if (y > 15) { - lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT); - lcdDrawNumber(x+GAUGE_WIDTH+1, y-6, barMax, TINSIZE); - } - if (weight < 0) { - barMin = -barMin; - barMax = -barMax; - } - if (barMin < -101) - barMin = -101; - if (barMax > 101) - barMax = 101; - lcdDrawHorizontalLine(x-2, y, GAUGE_WIDTH+2, DOTTED); - lcdDrawHorizontalLine(x-2, y+GAUGE_HEIGHT, GAUGE_WIDTH+2, DOTTED); - lcdDrawSolidVerticalLine(x-2, y+1, GAUGE_HEIGHT-1); - lcdDrawSolidVerticalLine(x+GAUGE_WIDTH-1, y+1, GAUGE_HEIGHT-1); - if (barMin <= barMax) { - int8_t right = (barMax * GAUGE_WIDTH) / 200; - int8_t left = ((barMin * GAUGE_WIDTH) / 200)-1; - lcdDrawSolidFilledRect(x+GAUGE_WIDTH/2+left, y+2, right-left, GAUGE_HEIGHT-3); - } - lcdDrawSolidVerticalLine(x+GAUGE_WIDTH/2-1, y, GAUGE_HEIGHT+1); - if (barMin == -101) { - for (uint8_t i=0; i<3; ++i) { - lcdDrawPoint(x+i, y+4-i); - lcdDrawPoint(x+3+i, y+4-i); - } - } - if (barMax == 101) { - for (uint8_t i=0; i<3; ++i) { - lcdDrawPoint(x+GAUGE_WIDTH-8+i, y+4-i); - lcdDrawPoint(x+GAUGE_WIDTH-5+i, y+4-i); - } - } -} -#undef GAUGE_WIDTH -#undef GAUGE_HEIGHT - -void menuModelMixOne(event_t event) -{ - title(STR_MIXES); - MixData * md2 = mixAddress(s_currIdx) ; - putsChn(lcdLastRightPos+1*FW, 0, md2->destCh+1,0); - - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {0, 0, 0, 0, 1, 1, CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); - - int8_t sub = menuVerticalPosition; - int8_t editMode = s_editMode; - - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - switch (i) { - case MIX_FIELD_NAME: - editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr); - break; - case MIX_FIELD_SOURCE: - drawFieldLabel(COLUMN_X, y, STR_SOURCE); - drawSource(COLUMN_X+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); - if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); - break; - case MIX_FIELD_WEIGHT: - drawFieldLabel(COLUMN_X, y, STR_WEIGHT); - gvarWeightItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); - break; - case MIX_FIELD_OFFSET: - { - drawFieldLabel(COLUMN_X, y, STR_OFFSET); - u_int8int16_t offset; - MD_OFFSET_TO_UNION(md2, offset); - offset.word = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN, y, offset.word, MIX_OFFSET_MIN, MIX_OFFSET_MAX, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); - drawOffsetBar(COLUMN_X+MIXES_2ND_COLUMN+22, y, md2); - break; - } - - case MIX_FIELD_TRIM: - { - uint8_t not_stick = (md2->srcRaw > NUM_STICKS); - int8_t carryTrim = -md2->carryTrim; - drawFieldLabel(COLUMN_X, y, STR_TRIM); - lcdDrawTextAtIndex((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+6*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0); - if (attr && menuHorizontalPosition==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - if (!not_stick) { - lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX); - drawCheckBox(COLUMN_X+MIXES_2ND_COLUMN+DREX_CHBOX_OFFSET, y, !md2->noExpo, menuHorizontalPosition==1 ? attr : 0); - if (attr && menuHorizontalPosition==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1); - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - } - - case MIX_FIELD_CURVE: - { - drawFieldLabel(COLUMN_X, y, STR_CURVE); - int8_t curveParam = md2->curveParam; - if (md2->curveMode == MODE_CURVE) { - drawCurveName(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr); - if (attr) { - if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){ - s_currIdxSubMenu = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE); - pushMenu(menuModelCurveOne); - } - else { - CHECK_INCDEC_MODELVAR(event, md2->curveParam, -MAX_CURVES, CURVE_BASE+MAX_CURVES-1); - if (md2->curveParam == 0) - md2->curveMode = MODE_DIFFERENTIAL; - } - } - } - else { - lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, "Diff", menuHorizontalPosition==0 ? attr : 0); - md2->curveParam = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, curveParam, -100, 100, LEFT|(menuHorizontalPosition==1 ? attr : 0), 0, editMode>0 ? event : 0); - if (attr && editMode>0 && menuHorizontalPosition==0) { - int8_t tmp = 0; - CHECK_INCDEC_MODELVAR(event, tmp, -1, 1); - if (tmp != 0) { - md2->curveMode = MODE_CURVE; - md2->curveParam = tmp; - } - } - } - break; - } -#if defined(FLIGHT_MODES) - case MIX_FIELD_FLIGHT_PHASE: - md2->flightModes = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->flightModes, attr); - break; -#endif - case MIX_FIELD_SWITCH: - md2->swtch = editSwitch(COLUMN_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event); - break; - case MIX_FIELD_WARNING: - drawFieldLabel(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING); - if (md2->mixWarn) - lcdDrawNumber(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT); - else - lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_OFF, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3); - break; - case MIX_FIELD_MLTPX: - md2->mltpx = editChoice(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event); - break; - case MIX_FIELD_DELAY_UP: - md2->delayUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYUP, md2->delayUp); - break; - case MIX_FIELD_DELAY_DOWN: - md2->delayDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYDOWN, md2->delayDown); - break; - case MIX_FIELD_SLOW_UP: - md2->speedUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWUP, md2->speedUp); - break; - case MIX_FIELD_SLOW_DOWN: - md2->speedDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWDOWN, md2->speedDown); - break; - } - } -} - -#define _STR_MAX(x) "/" #x -#define STR_MAX(x) _STR_MAX(x) - - #define EXPO_LINE_WEIGHT_POS 7*FW+1 - #define EXPO_LINE_EXPO_POS 10*FW+5 - #define EXPO_LINE_SWITCH_POS 11*FW+2 - #define EXPO_LINE_SIDE_POS 14*FW+2 - #define EXPO_LINE_SELECT_POS 24 - #define EXPO_LINE_FM_POS - #define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW - #define MIX_LINE_SRC_POS 4*FW-1 - #define MIX_LINE_WEIGHT_POS 11*FW+3 - #define MIX_LINE_CURVE_POS 12*FW+2 - #define MIX_LINE_SWITCH_POS 16*FW - #define MIX_LINE_DELAY_POS 19*FW+7 - -void onExpoMixMenu(const char *result) -{ - bool expo = (menuHandlers[menuLevel] == menuModelExposAll); - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - if (result == STR_EDIT) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { - if (!reachExpoMixCountLimit(expo)) { - s_currCh = chn; - if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - } - else if (result == STR_COPY || result == STR_MOVE) { - s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE); - s_copySrcIdx = s_currIdx; - s_copySrcCh = chn; - s_copySrcRow = menuVerticalPosition; - } - else if (result == STR_DELETE) { - deleteExpoMix(expo, s_currIdx); - } -} - -void displayMixInfos(coord_t y, MixData *md) -{ - if (md->curveParam) { - if (md->curveMode == MODE_CURVE) - drawCurveName(MIX_LINE_CURVE_POS, y, md->curveParam); - else - displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100); - } - - if (md->swtch) { - drawSwitch(MIX_LINE_SWITCH_POS, y, md->swtch); - } -} - -void displayMixLine(coord_t y, MixData * md) -{ - if (md->name[0]) { - lcdDrawSizedText(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR); - } - else { - displayMixInfos(y, md); - } -} - -void displayExpoInfos(coord_t y, ExpoData *ed) -{ - if (ed->curveMode == MODE_CURVE) - drawCurveName(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam); - else - displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100); - - drawSwitch(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); -} - -void displayExpoLine(coord_t y, ExpoData *ed) -{ - displayExpoInfos(y, ed); - - if (ed->name[0]) { - lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR); - } -} - -void menuModelExpoMix(uint8_t expo, event_t event) -{ - uint8_t sub = menuVerticalPosition; - - if (s_editMode > 0) - s_editMode = 0; - - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - switch (event) - { - case EVT_ENTRY: - case EVT_ENTRY_UP: - s_copyMode = 0; - s_copyTgtOfs = 0; - break; - case EVT_KEY_LONG(KEY_EXIT): - if (s_copyMode && s_copyTgtOfs == 0) { - deleteExpoMix(expo, s_currIdx); - killEvents(event); - event = 0; - } - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - if (s_copyMode) { - killEvents(event); - } -#endif - case EVT_KEY_BREAK(KEY_EXIT): - if (s_copyMode) { - if (s_copyTgtOfs) { - // cancel the current copy / move operation - if (s_copyMode == COPY_MODE) { - deleteExpoMix(expo, s_currIdx); - } - else { - do { - swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0); - s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); - } while (s_copyTgtOfs != 0); - storageDirty(EE_MODEL); - } - menuVerticalPosition = s_copySrcRow; - s_copyTgtOfs = 0; - } - s_copyMode = 0; - event = 0; - } - break; - case EVT_KEY_BREAK(KEY_ENTER): - if (sub != 0 && (!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) { - s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); - s_copySrcIdx = s_currIdx; - s_copySrcCh = chn; - s_copySrcRow = sub; - break; - } - // no break - - case EVT_KEY_LONG(KEY_ENTER): - killEvents(event); - if (s_copyTgtOfs) { - s_copyMode = 0; - s_copyTgtOfs = 0; - } - else if (sub != 0) { - if (READ_ONLY()) { - if (!s_currCh) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - return; - } - } - else { - if (s_copyMode) s_currCh = 0; - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - return; - } - else { - event = 0; - s_copyMode = 0; - POPUP_MENU_ADD_ITEM(STR_EDIT); - POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); - POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); - POPUP_MENU_ADD_ITEM(STR_COPY); - POPUP_MENU_ADD_ITEM(STR_MOVE); - POPUP_MENU_ADD_ITEM(STR_DELETE); - POPUP_MENU_START(onExpoMixMenu); - } - } - } - break; - case EVT_KEY_LONG(KEY_LEFT): - case EVT_KEY_LONG(KEY_RIGHT): - if (s_copyMode && !s_copyTgtOfs) { - if (reachExpoMixCountLimit(expo)) break; - s_currCh = chn; - if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - killEvents(event); - return; - } - break; -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LEFT: - case EVT_ROTARY_RIGHT: -#endif - case EVT_KEY_FIRST(KEY_UP): - case EVT_KEY_REPT(KEY_UP): - case EVT_KEY_FIRST(KEY_DOWN): - case EVT_KEY_REPT(KEY_DOWN): - if (s_copyMode) { - uint8_t key = (event & 0x1f); - uint8_t next_ofs = ((IS_ROTARY_LEFT(event) || key==KEY_UP) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1); - - if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) { - // insert a mix on the same channel (just above / just below) - if (reachExpoMixCountLimit(expo)) break; - copyExpoMix(expo, s_currIdx); - if (IS_ROTARY_RIGHT(event) || key==KEY_DOWN) s_currIdx++; - else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; - } - else if (next_ofs==0 && s_copyMode==COPY_MODE) { - // delete the mix - deleteExpoMix(expo, s_currIdx); - if (IS_ROTARY_LEFT(event) || key==KEY_UP) s_currIdx--; - } - else { - // only swap the mix with its neighbor - if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_LEFT(event) || key==KEY_UP)) break; - storageDirty(EE_MODEL); - } - - s_copyTgtOfs = next_ofs; - } - break; - } - - lcdDrawNumber(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXES))+FW+FW/2, 0, getExpoMixCount(expo)); - lcdDrawText(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXES))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS)); - - SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXES, menuTabModel, expo ? MENU_MODEL_INPUTS : MENU_MODEL_MIXES, s_maxLines); - - sub = menuVerticalPosition; - s_currCh = 0; - uint8_t cur = 1; - uint8_t i = 0; - - for (uint8_t ch=1; ch<=(expo ? MAX_INPUTS : MAX_OUTPUT_CHANNELS); ch++) { - void *pointer = nullptr; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; - coord_t y = MENU_HEADER_HEIGHT-FH+1+(cur-menuVerticalOffset)*FH; - if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { - if (menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES) { - if (expo) { - drawSource(0, y, MIXSRC_Rud+ch-1, 0); - } - else { - putsChn(0, y, ch, 0); // show CHx - } - } - uint8_t mixCnt = 0; - do { - if (s_copyMode) { - if (s_copyMode == MOVE_MODE && menuVerticalOffset < cur && cur-menuVerticalOffset < 8 && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcdDrawRect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - if (s_currIdx == i) { - sub = menuVerticalPosition = cur; - s_currCh = ch; - } - } - else if (sub == cur) { - s_currIdx = i; - } - if (menuVerticalOffset < cur && cur-menuVerticalOffset < 8) { - uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - if (expo) { - ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, -100, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event); - displayExpoLine(y, ed); - if (ed->mode!=3) { - lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); - } - } - else { - if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0); - - drawSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0); - - gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event); - - displayMixLine(y, md); - - char cs = ' '; - if (md->speedDown || md->speedUp) - cs = 'S'; - if (md->delayUp || md->delayDown) - cs = (cs =='S' ? '*' : 'D'); - lcdDrawChar(MIX_LINE_DELAY_POS, y, cs); - } - if (s_copyMode) { - if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - /* draw a border around the raw on selection mode (copy/move) */ - lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); - } - if (cur == sub) { - /* invert the raw when it's the current one */ - lcdDrawSolidFilledRect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7); - } - } - } - cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++; - } while (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)); - if (s_copyMode == MOVE_MODE && menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - } - else { - uint8_t attr = 0; - if (sub == cur) { - s_currIdx = i; - s_currCh = ch; - if (!s_copyMode) { - attr = INVERS; - } - } - if (menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES) { - if (expo) { - drawSource(0, y, MIXSRC_Rud+ch-1, attr); - } - else { - putsChn(0, y, ch, attr); // show CHx - } - if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { - lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED); - } - } - cur++; y+=FH; - } - } - s_maxLines = cur; - if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1; -} - -void menuModelExposAll(event_t event) -{ - return menuModelExpoMix(1, event); -} - -void menuModelMixAll(event_t event) -{ - return menuModelExpoMix(0, event); -} diff --git a/radio/src/gui/128x64/model_mix_edit.cpp b/radio/src/gui/128x64/model_mix_edit.cpp index d21e76e6f..a0168b0d7 100644 --- a/radio/src/gui/128x64/model_mix_edit.cpp +++ b/radio/src/gui/128x64/model_mix_edit.cpp @@ -91,7 +91,7 @@ void menuModelMixOne(event_t event) killEvents(event); } #elif defined(NAVIGATION_XLITE) - if (event == EVT_KEY_LONG(KEY_SHIFT)) { + if (event == EVT_KEY_FIRST(KEY_ENTER) && IS_SHIFT_PRESSED()) { pushMenu(menuChannelsView); killEvents(event); } @@ -150,6 +150,8 @@ void menuModelMixOne(event_t event) case MIX_FIELD_CURVE: lcdDrawTextAlignedLeft(y, STR_CURVE); + s_currSrcRaw = md2->srcRaw; + s_currScale = 0; editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, s_editMode > 0 ? event : 0, attr); break; diff --git a/radio/src/gui/128x64/model_select.cpp b/radio/src/gui/128x64/model_select.cpp index 19ee6a702..24f2b39fc 100644 --- a/radio/src/gui/128x64/model_select.cpp +++ b/radio/src/gui/128x64/model_select.cpp @@ -36,6 +36,10 @@ void onModelSelectMenu(const char * result) int8_t sub = menuVerticalPosition; if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) { + if (!g_eeGeneral.disableRssiPoweroffAlarm) { + if (!confirmModelChange()) + return; + } selectModel(sub); } else if (result == STR_COPY_MODEL) { diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 94252ffbc..1ba46c035 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -69,6 +69,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_THROTTLE_REVERSED, ITEM_MODEL_SETUP_THROTTLE_TRACE, ITEM_MODEL_SETUP_THROTTLE_TRIM, + ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH, ITEM_MODEL_SETUP_PREFLIGHT_LABEL, ITEM_MODEL_SETUP_CHECKLIST_DISPLAY, ITEM_MODEL_SETUP_THROTTLE_WARNING, @@ -121,12 +122,22 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_EXTERNAL_MODULE_SUBTYPE, ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS, +#endif +#if defined(AFHDS3) + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS_PROTOCOL, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS, #endif ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS, ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE, ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM, #if defined(PCBSKY9X) && defined(REVX) ITEM_MODEL_SETUP_EXTERNAL_MODULE_OUTPUT_TYPE, +#endif +#if defined(AFHDS3) + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER, #endif ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER, ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS, @@ -135,6 +146,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM, ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING, #endif + ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE, ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_REGISTER_RANGE, ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_OPTIONS, @@ -207,11 +219,6 @@ inline uint8_t MODULE_TYPE_ROWS(int moduleIdx) { if (isModuleXJT(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleDSM2(moduleIdx)) return 1; -#if defined(MULTIMODULE) - else if (isModuleMultimodule(moduleIdx)) { - return 0; - } -#endif else return 0; } @@ -303,6 +310,9 @@ void onBluetoothConnectMenu(const char * result) #if defined(PXX2) #include "common/stdlcd/model_setup_pxx2.cpp" #endif +#if defined(AFHDS3) +#include "common/stdlcd/model_setup_afhds3.cpp" +#endif #if defined(HARDWARE_INTERNAL_MODULE) #define INTERNAL_MODULE_ROWS \ @@ -348,6 +358,7 @@ void menuModelSetup(event_t event) 0, // Throttle reverse 0, // Throttle trace source 0, // Throttle trim + 0, // Throttle trim switch LABEL(PreflightCheck), 0, // Checklist @@ -367,9 +378,12 @@ void menuModelSetup(event_t event) MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE) // PROTOCOL MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) // SUBTYPE MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + AFHDS3_PROTOCOL_ROW(EXTERNAL_MODULE) + AFHDS3_MODE_ROWS(EXTERNAL_MODULE) MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum + AFHDS3_MODULE_ROWS(EXTERNAL_MODULE) MODULE_POWER_ROW(EXTERNAL_MODULE), IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) @@ -396,6 +410,7 @@ void menuModelSetup(event_t event) 0, // Throttle reverse 0, // Throttle trace source 0, // Throttle trim + 0, // Throttle trim switch LABEL(PreflightCheck), 0, // Checklist @@ -407,8 +422,10 @@ void menuModelSetup(event_t event) LABEL(ExternalModule), MODULE_TYPE_ROWS(EXTERNAL_MODULE), + MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE) MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum @@ -607,6 +624,13 @@ void menuModelSetup(event_t event) g_model.thrTrim = editCheckBox(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event); break; + case ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH: + lcdDrawTextAlignedLeft(y, STR_TTRIM_SW); + if (attr) + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTrimSw, NUM_TRIMS - 1); + drawSource(MODEL_SETUP_2ND_COLUMN, y, g_model.getThrottleStickTrimSource(), attr); + break; + case ITEM_MODEL_SETUP_PREFLIGHT_LABEL: lcdDrawTextAlignedLeft(y, STR_PREFLIGHT); break; @@ -1051,6 +1075,21 @@ void menuModelSetup(event_t event) break; #endif +#if defined(AFHDS3) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS_PROTOCOL: + lcdDrawTextAlignedLeft(y, TR_PROTO); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].subType, attr); + if (attr && s_editMode > 0 && menuHorizontalPosition == 0) { + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST); + } + break; + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE: + lcdDrawText(INDENT_WIDTH, y, TR_TELEMETRY_TYPE); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, + g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry ? STR_AFHDS3_ONE_TO_ONE_TELEMETRY : TR_AFHDS3_ONE_TO_MANY); + break; +#endif + #if defined(PCBTARANIS) case ITEM_MODEL_SETUP_TRAINER_LABEL: lcdDrawTextAlignedLeft(y, STR_TRAINER); @@ -1060,7 +1099,7 @@ void menuModelSetup(event_t event) lcdDrawTextAlignedLeft(y, INDENT TR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr); if (attr) { - g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX, EE_MODEL, isTrainerModeAvailable); + g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable); #if defined(BLUETOOTH) if (checkIncDec_Ret) { bluetooth.state = BLUETOOTH_STATE_OFF; @@ -1320,15 +1359,12 @@ void menuModelSetup(event_t event) if (isModuleRxNumAvailable(moduleIdx)) { lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2); bindButtonPos = lcdNextPos + 2; - } - else if (attr) { - l_posHorz += 1; - } - if (isModuleBindRangeAvailable(moduleIdx)) { if (attr && l_posHorz == 0) { if (s_editMode > 0) { CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx)); if (checkIncDec_Ret) { + if (isModuleCrossfire(moduleIdx)) + moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID; modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx]; } else if (event == EVT_KEY_LONG(KEY_ENTER)) { @@ -1341,6 +1377,11 @@ void menuModelSetup(event_t event) } } } + } + else if (attr) { + l_posHorz += 1; + } + if (isModuleBindRangeAvailable(moduleIdx)) { lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0); if (isModuleRangeAvailable(moduleIdx)) { lcdDrawText(lcdNextPos + 2, y, STR_MODULE_RANGE, l_posHorz == 2 ? attr : 0); @@ -1356,7 +1397,7 @@ void menuModelSetup(event_t event) if (attr && l_posHorz > 0) { if (s_editMode > 0) { if (l_posHorz == 1) { - if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx)) { + if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx) || isModuleAFHDS3(moduleIdx)) { #if defined(PCBXLITE) if (EVT_KEY_MASK(event) == KEY_ENTER) { #elif defined(NAVIGATION_9X) @@ -1365,6 +1406,12 @@ void menuModelSetup(event_t event) if (event == EVT_KEY_BREAK(KEY_ENTER)) { #endif killEvents(event); +#if defined(AFHDS3) + if (isModuleAFHDS3(moduleIdx)) { + startBindMenuAfhds3(moduleIdx); + continue; + } +#endif startBindMenu(moduleIdx); continue; } @@ -1510,15 +1557,35 @@ void menuModelSetup(event_t event) } } + int8_t min, max; + getMultiOptionValues(multi_proto, min, max); - if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) - optionValue = 50 + 5 * optionValue; - - lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr); + if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) { + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr); + } + else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) { + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr); + } + else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) { + optionValue = optionValue & 0x01; + editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event); + } + else { + if (min == 0 && max == 1) + editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event); + else + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr); + } if (attr) { - int8_t min, max; - getMultiOptionValues(multi_proto, min, max); - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, min, max); + CHECK_INCDEC_MODELVAR(event, optionValue, min, max); + if (checkIncDec_Ret) { + if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) { + g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFE) + optionValue; + } + else { + g_model.moduleData[moduleIdx].multi.optionValue = optionValue; + } + } } } #endif @@ -1608,6 +1675,14 @@ void menuModelSetup(event_t event) module.multi.lowPowerMode = editCheckBox(module.multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, IS_RX_MULTI(moduleIdx) ? STR_MULTI_LNA_DISABLE : STR_MULTI_LOWPOWER, attr, event); } #endif +#if defined(AFHDS3) + else if (isModuleAFHDS3(EXTERNAL_MODULE)) { + lcdDrawText(INDENT_WIDTH, y, STR_RFPOWER); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, LEFT | attr); + if (attr) + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, afhds3::RUN_POWER::RUN_POWER_FIRST, afhds3::RUN_POWER::RUN_POWER_LAST); + } +#endif } break; @@ -1617,42 +1692,89 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND: - if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) - g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_DSM_AUTODTECT, attr, event); - else - g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_AUTOBIND, attr, event); + if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) { + int8_t value = (g_model.moduleData[moduleIdx].multi.optionValue & 0x02) >> 1; + lcdDrawText(INDENT_WIDTH, y, STR_MULTI_SERVOFREQ); + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, value ? 11 : 22, attr); + lcdDrawText(lcdNextPos, y, "ms", attr); + if (attr) { + CHECK_INCDEC_MODELVAR(event, value, 0, 1); + if (checkIncDec_Ret) { + g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFD) + (value << 1); + } + } + } + else { + g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, + STR_MULTI_AUTOBIND, attr, event); + } break; + #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_TELEM: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM: g_model.moduleData[moduleIdx].multi.disableTelemetry = editCheckBox(g_model.moduleData[moduleIdx].multi.disableTelemetry, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_TELEM, attr, event); break; + #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_MAPPING: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING: g_model.moduleData[moduleIdx].multi.disableMapping = editCheckBox(g_model.moduleData[moduleIdx].multi.disableMapping, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_CH_MAP, attr, event); break; +#endif +#if defined(AFHDS3) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ: + lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_RX_FREQ); + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq(), attr | LEFT); + if (attr) { + uint16_t rxFreq = g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq(); + CHECK_INCDEC_MODELVAR(event, rxFreq, MIN_FREQ, MAX_FREQ); + g_model.moduleData[EXTERNAL_MODULE].afhds3.setRxFreq(rxFreq); + } + break; + + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER: + lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_ACTUAL_POWER); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, actualAfhdsRunPower(EXTERNAL_MODULE), LEFT); + break; +#endif + +#if defined(MULTIMODULE) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS: #endif - case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: { + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS); - - getMultiModuleStatus(moduleIdx).getStatusString(reusableBuffer.moduleSetup.msg); + getModuleStatusString(EXTERNAL_MODULE, reusableBuffer.moduleSetup.msg); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg); break; - } + #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS: #endif - case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: { + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC); + getModuleSyncStatusString(moduleIdx, reusableBuffer.moduleSetup.msg); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg); + break; +#endif + +#if defined(AFHDS3) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS: { + lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS); char statusText[64]; - getMultiSyncStatus(moduleIdx).getRefreshString(statusText); + getModuleStatusString(moduleIdx, statusText); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); + break; + } + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS: { + lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_POWER_SOURCE); + char statusText[64]; + getModuleSyncStatusString(moduleIdx, statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } @@ -1702,7 +1824,6 @@ void menuModelSetup(event_t event) } break; #endif - } } diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp index 2eaad8f2b..c85cdf2f2 100644 --- a/radio/src/gui/128x64/model_special_functions.cpp +++ b/radio/src/gui/128x64/model_special_functions.cpp @@ -338,6 +338,14 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF INCDEC_ENABLE_CHECK(isSourceAvailable); } } + else if (func == FUNC_BACKLIGHT) { + val_max = MIXSRC_LAST_CH; + drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); + if (active) { + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } + } #if defined(SDCARD) else if (func == FUNC_LOGS) { if (val_displayed) { diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp index a5840754a..a3d058c3e 100644 --- a/radio/src/gui/128x64/radio_diagkeys.cpp +++ b/radio/src/gui/128x64/radio_diagkeys.cpp @@ -76,6 +76,6 @@ void menuRadioDiagKeys(event_t event) #if defined(ROTARY_ENCODER_NAVIGATION) coord_t y = MENU_HEADER_HEIGHT + 1 + FH*KEY_COUNT; lcdDrawText(0, y, STR_ROTARY_ENCODER); - lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue, RIGHT); + lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue / ROTARY_ENCODER_GRANULARITY, RIGHT); #endif } diff --git a/radio/src/gui/128x64/view_telemetry.cpp b/radio/src/gui/128x64/view_telemetry.cpp index 86d369377..3b6835f64 100644 --- a/radio/src/gui/128x64/view_telemetry.cpp +++ b/radio/src/gui/128x64/view_telemetry.cpp @@ -68,27 +68,20 @@ bool displayGaugesTelemetryScreen(TelemetryScreenData & screen) barMin = calc100toRESX(barMin); barMax = calc100toRESX(barMax); } - if (source && barMax > barMin) { + if (source) { uint8_t y = barHeight+6+i*(barHeight+6); drawSource(0, y+barHeight/2-3, source, SMLSIZE); lcdDrawRect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2); getvalue_t value = getValue(source); - uint8_t thresholdX = 0; - - - uint8_t width = barCoord(value, barMin, barMax); - + uint8_t width = (barMin < barMax) ? barCoord(value, barMin, barMax) : 99 - barCoord(value, barMax, barMin); uint8_t barShade = SOLID; - lcdDrawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade); - for (uint8_t j=24; j<99; j+=25) { if (j>thresholdX || j>width) { lcdDrawSolidVerticalLine(j*BAR_WIDTH/100+BAR_LEFT+1, y+1, barHeight); } } - if (thresholdX) { lcdDrawVerticalLine(BAR_LEFT+1+thresholdX, y-2, barHeight+3, DOTTED); lcdDrawSolidHorizontalLine(BAR_LEFT+thresholdX, y-2, 3); diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp index 6116cc2f9..3df4e3a31 100644 --- a/radio/src/gui/128x64/widgets.cpp +++ b/radio/src/gui/128x64/widgets.cpp @@ -67,7 +67,11 @@ void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uin void drawGauge(coord_t x, coord_t y, coord_t w, coord_t h, int32_t val, int32_t max) { +#if defined(PCBX7) || defined(PCBX9LITES) // X7 LCD doesn't like too many horizontal lines + h++; +#else lcdDrawRect(x, y, w+1, h); +#endif lcdDrawFilledRect(x+1, y+1, w-1, 4, SOLID, ERASE); coord_t len = limit((uint8_t)1, uint8_t((abs(val) * w/2 + max/2) / max), uint8_t(w/2)); coord_t x0 = (val>0) ? x+w/2 : x+1+w/2-len; diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h index 763c5f7c6..bb2e0d630 100644 --- a/radio/src/gui/212x64/gui.h +++ b/radio/src/gui/212x64/gui.h @@ -245,6 +245,8 @@ extern int8_t s_copySrcRow; extern int8_t s_copyTgtOfs; extern uint8_t s_currIdx; extern uint8_t s_currIdxSubMenu; +extern uint16_t s_currSrcRaw; +extern uint16_t s_currScale; extern uint8_t s_maxLines; extern uint8_t s_copySrcIdx; extern uint8_t s_copySrcCh; @@ -282,9 +284,6 @@ void menuChannelsView(event_t event); #define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0) #define EDIT_MODE_INIT 0 // TODO enum -typedef int (*FnFuncP) (int x); -void drawFunction(FnFuncP fn, uint8_t offset=0); - void onSourceLongEnterPress(const char *result); uint8_t switchToMix(uint8_t source); diff --git a/radio/src/gui/212x64/menu_model.cpp b/radio/src/gui/212x64/menu_model.cpp index 329220305..a2143d61e 100644 --- a/radio/src/gui/212x64/menu_model.cpp +++ b/radio/src/gui/212x64/menu_model.cpp @@ -69,3 +69,5 @@ void editSingleName(coord_t x, coord_t y, const char * label, char *name, uint8_ uint8_t s_currIdx; uint8_t s_currIdxSubMenu; +uint16_t s_currSrcRaw; +uint16_t s_currScale; diff --git a/radio/src/gui/212x64/model_curve_edit.cpp b/radio/src/gui/212x64/model_curve_edit.cpp index c98af6ba1..5a79d07a2 100644 --- a/radio/src/gui/212x64/model_curve_edit.cpp +++ b/radio/src/gui/212x64/model_curve_edit.cpp @@ -180,6 +180,8 @@ void menuModelCurveOne(event_t event) } drawCurve(FW); + if (s_currSrcRaw != MIXSRC_NONE) + drawCursor(applyCurrentCurve, FW); uint8_t posY = FH+1; attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); diff --git a/radio/src/gui/212x64/model_display.cpp b/radio/src/gui/212x64/model_display.cpp index 081b70f67..de7dc48a9 100644 --- a/radio/src/gui/212x64/model_display.cpp +++ b/radio/src/gui/212x64/model_display.cpp @@ -245,10 +245,10 @@ void menuModelDisplay(event_t event) } break; case 1: - bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS); + bar.barMin = checkIncDec(event, bar.barMin, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); break; case 2: - bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); + bar.barMax = checkIncDec(event, bar.barMax, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); break; } } diff --git a/radio/src/gui/212x64/model_input_edit.cpp b/radio/src/gui/212x64/model_input_edit.cpp index dc5e6085b..6882f040b 100644 --- a/radio/src/gui/212x64/model_input_edit.cpp +++ b/radio/src/gui/212x64/model_input_edit.cpp @@ -30,28 +30,6 @@ int expoFn(int x) return anas[ed->chn]; } -void drawFunction(FnFuncP fn, uint8_t offset) -{ - lcdDrawVerticalLine(CURVE_CENTER_X-offset, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, CURVE_SIDE_WIDTH*2, 0xee); - lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee); - - coord_t prev_yv = (coord_t)-1; - - for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) { - coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX); - if (prev_yv != (coord_t)-1) { - if (abs((int8_t)yv-prev_yv) <= 1) { - lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE); - } - else { - uint8_t tmp = (prev_yv < yv ? 0 : 1); - lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv); - } - } - prev_yv = yv; - } -} - enum ExposFields { EXPO_FIELD_INPUT_NAME, EXPO_FIELD_LINE_NAME, @@ -109,7 +87,15 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr); - if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); + if (attr && menuHorizontalPosition==0) + ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); + if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { + drawSensorCustomValue(EXPO_ONE_2ND_COLUMN+30, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, getValue(ed->srcRaw), LEFT|(menuHorizontalPosition==1?attr:0)); + if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); + } + else if (attr) { + menuHorizontalPosition = 0; + } break; case EXPO_FIELD_SCALE: @@ -160,23 +146,8 @@ void menuModelExpoOne(event_t event) } drawFunction(expoFn); - - int x512 = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - drawSensorCustomValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); - if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); - } - else { - lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), RIGHT | PREC1); - } - x512 = limit(-1024, x512, 1024); - int y512 = expoFn(x512); - y512 = limit(-1024, y512, 1024); - lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), RIGHT | PREC1); - - x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH); - y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; - - lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1); - lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1); + // those parameters are global so that they can be reused in the curve edit screen + s_currSrcRaw = ed->srcRaw; + s_currScale = ed->scale; + drawCursor(expoFn); } diff --git a/radio/src/gui/212x64/model_mix_edit.cpp b/radio/src/gui/212x64/model_mix_edit.cpp index 0007d91ee..b46d678a9 100644 --- a/radio/src/gui/212x64/model_mix_edit.cpp +++ b/radio/src/gui/212x64/model_mix_edit.cpp @@ -140,6 +140,8 @@ void menuModelMixOne(event_t event) case MIX_FIELD_CURVE: lcdDrawTextAlignedLeft(y, STR_CURVE); + s_currSrcRaw = md2->srcRaw; + s_currScale = 0; editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr); break; diff --git a/radio/src/gui/212x64/model_select.cpp b/radio/src/gui/212x64/model_select.cpp index 6b5282c15..0de110afc 100644 --- a/radio/src/gui/212x64/model_select.cpp +++ b/radio/src/gui/212x64/model_select.cpp @@ -27,6 +27,10 @@ void onModelSelectMenu(const char * result) int8_t sub = menuVerticalPosition; if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) { + if (!g_eeGeneral.disableRssiPoweroffAlarm) { + if (!confirmModelChange()) + return; + } selectModel(sub); } else if (result == STR_COPY_MODEL) { diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 8d836e13e..ec57909de 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -66,6 +66,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_THROTTLE_REVERSED, ITEM_MODEL_SETUP_THROTTLE_TRACE, ITEM_MODEL_SETUP_THROTTLE_TRIM, + ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH, ITEM_MODEL_SETUP_PREFLIGHT_LABEL, ITEM_MODEL_SETUP_CHECKLIST_DISPLAY, ITEM_MODEL_SETUP_THROTTLE_WARNING, @@ -101,6 +102,11 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL, ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS, +#endif +#if defined(AFHDS3) + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS, #endif ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS, ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE, @@ -110,6 +116,10 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND, ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM, ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING, +#endif +#if defined(AFHDS3) + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ, + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER, #endif ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER, ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE, @@ -247,7 +257,7 @@ void editTimerCountdown(int timerIdx, coord_t y, LcdFlags attr, event_t event) inline uint8_t EXTERNAL_MODULE_TYPE_ROW() { - if (isModuleXJT(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE)) + if (isModuleXJT(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleAFHDS3(EXTERNAL_MODULE)) return 1; else return 0; @@ -304,6 +314,10 @@ void onBluetoothConnectMenu(const char * result) #if defined(PXX2) #include "common/stdlcd/model_setup_pxx2.cpp" #endif +#if defined(AFHDS3) +#include "common/stdlcd/model_setup_afhds3.cpp" +#endif + void menuModelSetup(event_t event) { @@ -331,6 +345,7 @@ void menuModelSetup(event_t event) 0, // Thrxottle reverse 0, // Throttle trace source 0, // Throttle trim + 0, // Throttle trim switch LABEL(PreflightCheck), 0, // Checklist @@ -360,11 +375,13 @@ void menuModelSetup(event_t event) EXTERNAL_MODULE_TYPE_ROW(), MULTIMODULE_TYPE_ROW(EXTERNAL_MODULE) MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + AFHDS3_MODE_ROWS(EXTERNAL_MODULE) MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum for ACCESS IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) + AFHDS3_MODULE_ROWS(EXTERNAL_MODULE) MODULE_POWER_ROW(EXTERNAL_MODULE), FAILSAFE_ROWS(EXTERNAL_MODULE), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons @@ -556,6 +573,13 @@ void menuModelSetup(event_t event) g_model.thrTrim = editCheckBox(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event); break; + case ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH: + lcdDrawTextAlignedLeft(y, STR_TTRIM_SW); + if (attr) + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTrimSw, NUM_TRIMS - 1); + drawSource(MODEL_SETUP_2ND_COLUMN, y, g_model.getThrottleStickTrimSource(), attr); + break; + case ITEM_MODEL_SETUP_PREFLIGHT_LABEL: lcdDrawTextAlignedLeft(y, STR_PREFLIGHT); break; @@ -810,6 +834,11 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0); else if (isModuleR9MNonAccess(EXTERNAL_MODULE)) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0)); +#if defined(AFHDS3) + else if (isModuleAFHDS3(EXTERNAL_MODULE)) { + lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_AFHDS3_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0)); + } +#endif if (attr && menuHorizontalPosition == 0) { if (s_editMode > 0) { g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_NONE; @@ -850,6 +879,11 @@ void menuModelSetup(event_t event) MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_LAST, EE_MODEL, isR9MModeAvailable); } +#if defined(AFHDS3) + else if (isModuleAFHDS3(EXTERNAL_MODULE)) { + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST); + } +#endif else { g_model.moduleData[EXTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].subType, MODULE_SUBTYPE_PXX1_ACCST_D16, MODULE_SUBTYPE_PXX1_LAST, EE_MODEL, @@ -898,6 +932,7 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL: { lcdDrawTextAlignedLeft(y, TR_TYPE); + uint8_t multi_rfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(); lcdDrawMultiProtocolString(MODEL_SETUP_2ND_COLUMN, y, EXTERNAL_MODULE, multi_rfProto, menuHorizontalPosition == 0 ? attr : 0); if (MULTIMODULE_HAS_SUBTYPE(EXTERNAL_MODULE)) @@ -946,7 +981,6 @@ void menuModelSetup(event_t event) } break; #endif - case ITEM_MODEL_SETUP_TRAINER_LABEL: lcdDrawTextAlignedLeft(y, STR_TRAINER); break; @@ -955,7 +989,7 @@ void menuModelSetup(event_t event) lcdDrawTextAlignedLeft(y, INDENT TR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr); if (attr) { - g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX, EE_MODEL, isTrainerModeAvailable); + g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable); #if defined(BLUETOOTH) if (checkIncDec_Ret) { bluetooth.state = BLUETOOTH_STATE_OFF; @@ -1135,15 +1169,12 @@ void menuModelSetup(event_t event) if (isModuleRxNumAvailable(moduleIdx)) { lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz == 0 ? attr : 0) | LEADING0 | LEFT, 2); bindButtonPos = lcdNextPos + FW; - } - else if (attr) { - l_posHorz += 1; - } - if (isModuleBindRangeAvailable(moduleIdx)) { if (attr && l_posHorz == 0) { if (s_editMode > 0) { CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx)); if (checkIncDec_Ret) { + if (isModuleCrossfire(moduleIdx)) + moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID; modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx]; } else if (event == EVT_KEY_LONG(KEY_ENTER)) { @@ -1156,6 +1187,11 @@ void menuModelSetup(event_t event) } } } + } + else if (attr) { + l_posHorz += 1; + } + if (isModuleBindRangeAvailable(moduleIdx)) { lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0); if (isModuleRangeAvailable(moduleIdx)) { lcdDrawText(lcdNextPos + FW, y, STR_MODULE_RANGE, l_posHorz == 2 ? attr : 0); @@ -1170,8 +1206,14 @@ void menuModelSetup(event_t event) if (attr && l_posHorz > 0) { if (s_editMode > 0) { if (l_posHorz == 1) { - if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx)) { + if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx) || isModuleAFHDS3(moduleIdx)) { if (event == EVT_KEY_BREAK(KEY_ENTER)) { +#if defined(AFHDS3) + if (isModuleAFHDS3(moduleIdx)) { + startBindMenuAfhds3(moduleIdx); + continue; + } +#endif startBindMenu(moduleIdx); continue; } @@ -1275,14 +1317,35 @@ void menuModelSetup(event_t event) } } - if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) - optionValue = 50 + 5 * optionValue; + int8_t min, max; + getMultiOptionValues(multi_proto, min, max); - lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr); + if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) { + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr); + } + else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) { + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr); + } + else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) { + optionValue = optionValue & 0x01; + editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event); + } + else { + if (min == 0 && max == 1) + editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event); + else + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr); + } if (attr) { - int8_t min, max; - getMultiOptionValues(multi_proto, min, max); - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, min, max); + CHECK_INCDEC_MODELVAR(event, optionValue, min, max); + if (checkIncDec_Ret) { + if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) { + g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFE) + optionValue; + } + else { + g_model.moduleData[moduleIdx].multi.optionValue = optionValue; + } + } } } #endif @@ -1327,16 +1390,35 @@ void menuModelSetup(event_t event) else if (isModuleMultimodule(moduleIdx)) { g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, IS_RX_MULTI(moduleIdx) ? STR_MULTI_LNA_DISABLE : STR_MULTI_LOWPOWER, attr, event); } +#endif +#if defined(AFHDS3) + else if (isModuleAFHDS3(EXTERNAL_MODULE)) { + lcdDrawText(INDENT_WIDTH, y, STR_RFPOWER); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, LEFT | attr); + if (attr) + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, afhds3::RUN_POWER::RUN_POWER_FIRST, afhds3::RUN_POWER::RUN_POWER_LAST); + } #endif break; } #if defined (MULTIMODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND: - if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) - g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_DSM_AUTODTECT, attr, event); - else + if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) { + int8_t value = (g_model.moduleData[EXTERNAL_MODULE].multi.optionValue & 0x02) >> 1; + lcdDrawText(INDENT_WIDTH, y, STR_MULTI_SERVOFREQ); + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, value ? 11 : 22, attr); + lcdDrawText(lcdNextPos, y, "ms", attr); + if (attr) { + CHECK_INCDEC_MODELVAR(event, value, 0, 1); + if (checkIncDec_Ret) { + g_model.moduleData[EXTERNAL_MODULE].multi.optionValue = (g_model.moduleData[EXTERNAL_MODULE].multi.optionValue & 0xFD) + (value << 1); + } + } + } + else { g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_AUTOBIND, attr, event); + } break; case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM: @@ -1346,25 +1428,63 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING: g_model.moduleData[EXTERNAL_MODULE].multi.disableMapping = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.disableMapping, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_CH_MAP, attr, event); break; +#endif +#if defined(AFHDS3) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ: + lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_RX_FREQ); + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq(), attr | LEFT); + if (attr) { + uint16_t rxFreq = g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq(); + CHECK_INCDEC_MODELVAR(event, rxFreq, MIN_FREQ, MAX_FREQ); + g_model.moduleData[EXTERNAL_MODULE].afhds3.setRxFreq(rxFreq); + } + break; + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER: + lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_ACTUAL_POWER); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, actualAfhdsRunPower(EXTERNAL_MODULE), LEFT); + break; +#endif + +#if defined (MULTIMODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: - { lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS); - getMultiModuleStatus(EXTERNAL_MODULE).getStatusString(reusableBuffer.moduleSetup.msg); + getModuleStatusString(EXTERNAL_MODULE, reusableBuffer.moduleSetup.msg); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg); break; - } case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: + lcdDrawText(INDENT_WIDTH, y, STR_MODULE_SYNC); + getModuleSyncStatusString(EXTERNAL_MODULE, reusableBuffer.moduleSetup.msg); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg); + break; +#endif + +#if defined (AFHDS3) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE: + lcdDrawTextAlignedLeft(y, STR_TYPE); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, + g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry ? STR_AFHDS3_ONE_TO_ONE_TELEMETRY : TR_AFHDS3_ONE_TO_MANY); + break; + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS: { - lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC); + lcdDrawTextAlignedLeft(y, TR_MODULE_STATUS); char statusText[64]; - getMultiSyncStatus(EXTERNAL_MODULE).getRefreshString(statusText); + getModuleStatusString(EXTERNAL_MODULE, statusText); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); + break; + } + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS: + { + lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_POWER_SOURCE); + char statusText[64]; + getModuleSyncStatusString(EXTERNAL_MODULE, statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } #endif + #if defined(PXX2) case ITEM_MODEL_SETUP_REGISTRATION_ID: lcdDrawTextAlignedLeft(y, STR_REG_ID); diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp index 7c2d1e139..c8b74a124 100644 --- a/radio/src/gui/212x64/model_special_functions.cpp +++ b/radio/src/gui/212x64/model_special_functions.cpp @@ -338,14 +338,14 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF lcdDrawMMM(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, attr); } } -#if defined(PCBX9E) || defined(PCBX9DP) else if (func == FUNC_BACKLIGHT) { - drawSlider(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, CFN_PARAM(cfn), 100, attr); - if (active) INCDEC_SET_FLAG(eeFlags | NO_INCDEC_MARKS); - val_min = 0; - val_max = 100; + val_max = MIXSRC_LAST_CH; + drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); + if (active) { + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } } -#endif #if defined(GVARS) else if (func == FUNC_ADJUST_GVAR) { switch (CFN_GVAR_MODE(cfn)) { diff --git a/radio/src/gui/212x64/radio_diagkeys.cpp b/radio/src/gui/212x64/radio_diagkeys.cpp index 56b8d102c..acb883513 100644 --- a/radio/src/gui/212x64/radio_diagkeys.cpp +++ b/radio/src/gui/212x64/radio_diagkeys.cpp @@ -59,6 +59,6 @@ void menuRadioDiagKeys(event_t event) #if defined(ROTARY_ENCODER_NAVIGATION) coord_t y = MENU_HEADER_HEIGHT + 1 + FH*KEY_COUNT; lcdDrawText(0, y, STR_ROTARY_ENCODER); - lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue, RIGHT); + lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue / ROTARY_ENCODER_GRANULARITY, RIGHT); #endif } diff --git a/radio/src/gui/212x64/view_telemetry.cpp b/radio/src/gui/212x64/view_telemetry.cpp index fa8740667..e15fc5781 100644 --- a/radio/src/gui/212x64/view_telemetry.cpp +++ b/radio/src/gui/212x64/view_telemetry.cpp @@ -66,14 +66,14 @@ void displayGaugesTelemetryScreen(TelemetryScreenData & screen) barMin = calc100toRESX(barMin); barMax = calc100toRESX(barMax); } - if (source && barMax > barMin) { + if (source) { int y = barHeight+6+i*(barHeight+6); drawSource(0, y+barHeight-5, source, 0); lcdDrawRect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2); getvalue_t value = getValue(source); drawSourceValue(BAR_LEFT+2+BAR_WIDTH, y+barHeight-5, source, LEFT); uint8_t thresholdX = 0; - int width = barCoord(value, barMin, barMax); + uint8_t width = (barMin < barMax) ? barCoord(value, barMin, barMax) : limit(0, 151 - barCoord(value, barMax, barMin), 151); uint8_t barShade = SOLID; lcdDrawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade); for (uint8_t j=24; j<99; j+=25) { diff --git a/radio/src/gui/colorlcd/colors.h b/radio/src/gui/colorlcd/colors.h index 1394c8652..4943e5f77 100644 --- a/radio/src/gui/colorlcd/colors.h +++ b/radio/src/gui/colorlcd/colors.h @@ -24,6 +24,7 @@ #include "libopenui_config.h" #define WHITE RGB(0xFF, 0xFF, 0xFF) +#define LIGHTWHITE RGB(238, 234, 238) #define BLACK RGB(0, 0, 0) #define YELLOW RGB(0xF0, 0xD0, 0x10) #define BLUE RGB(0x30, 0xA0, 0xE0) @@ -34,6 +35,10 @@ #define RED RGB(229, 32, 30) #define DARKRED RGB(160, 0, 6) #define GREEN RGB(25, 150, 50) +#define LIGHTBROWN RGB(156, 109, 32) +#define DARKBROWN RGB(106, 72, 16) +#define BRIGHTGREEN RGB(0, 180, 60) +#define ORANGE RGB(229, 100, 30) #define TEXT_STATUSBAR_COLOR COLOR(TEXT_STATUSBAR_COLOR_INDEX) #define LINE_COLOR COLOR(LINE_COLOR_INDEX) diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 0c7239107..b39f07c62 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -18,8 +18,7 @@ * GNU General Public License for more details. */ -#ifndef _LAYOUT_H_ -#define _LAYOUT_H_ +#pragma once #include #include "widgets_container.h" @@ -125,5 +124,3 @@ Layout * loadLayout(const char * name, Layout::PersistentData * persistentData); void loadCustomScreens(); std::list & getRegisteredLayouts(); - -#endif // _LAYOUT_H_ diff --git a/radio/src/gui/colorlcd/model_select_old.cpp b/radio/src/gui/colorlcd/model_select_old.cpp index 0b70b2966..0f268dfd8 100644 --- a/radio/src/gui/colorlcd/model_select_old.cpp +++ b/radio/src/gui/colorlcd/model_select_old.cpp @@ -242,6 +242,10 @@ void onDeleteModelConfirm(const char * result) void onModelSelectMenu(const char * result) { if (result == STR_SELECT_MODEL) { + if (!g_eeGeneral.disableRssiPoweroffAlarm) { + if (!confirmModelChange()) + return; + } // we store the latest changes if any storageFlushCurrentModel(); storageCheck(true); @@ -259,6 +263,10 @@ void onModelSelectMenu(const char * result) deleteMode = MODE_DELETE_MODEL; } else if (result == STR_CREATE_MODEL) { + if (!g_eeGeneral.disableRssiPoweroffAlarm) { + if (!confirmModelChange()) + return; + } storageCheck(true); modelslist.addModel(currentCategory, createModel()); selectMode = MODE_SELECT_MODEL; diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 1b125dd7e..f12a6aaa7 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -711,9 +711,9 @@ class ModuleWindow : public FormGroup { } #endif #if defined (PCBNV14) - else if (isModuleFlysky(moduleIdx)) { + else if (isModuleAFHDS3(moduleIdx)) { grid.nextLine(); - rfChoice = new Choice(this, grid.getFieldSlot(), STR_FLYSKY_PROTOCOLS, 0, 3, + rfChoice = new Choice(this, grid.getFieldSlot(), STR_AFHDS3_PROTOCOLS, 0, 3, GET_DEFAULT(g_model.moduleData[moduleIdx].flysky.mode), [=](int32_t newValue) -> void { g_model.moduleData[moduleIdx].flysky.mode = newValue; diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp index 6b3dfac5c..bbba31857 100644 --- a/radio/src/gui/colorlcd/widgets/gauge.cpp +++ b/radio/src/gui/colorlcd/widgets/gauge.cpp @@ -49,14 +49,16 @@ void GaugeWidget::refresh() uint16_t color = persistentData->options[3].value.unsignedValue; int32_t value = getValue(index); - int32_t value_in_range = value; - if (value < min) - value_in_range = min; - else if (value > max) - value_in_range = max; - int w = divRoundClosest(zone.w * (value_in_range - min), (max - min)); - int percent = divRoundClosest(100 * (value_in_range - min), (max - min)); + if (min > max) { + SWAP(min, max); + value = value - min - max; + } + + value = limit(min, value, max); + + int w = divRoundClosest(zone.w * (value - min), (max - min)); + int percent = divRoundClosest(100 * (value - min), (max - min)); // Gauge label drawSource(zone.x, zone.y, index, FONT(XS) | FOCUS_COLOR); diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index 71605a858..cc2e3e591 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -30,7 +30,7 @@ class ModelBitmapWidget: public Widget { } - virtual ~ModelBitmapWidget() + ~ModelBitmapWidget() override { delete buffer; } diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index 4bfab133e..a00c1200a 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -97,7 +97,7 @@ void ValueWidget::refresh() if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) { TimerState & timerState = timersStates[field-MIXSRC_FIRST_TIMER]; if (timerState.val < 0) { - lcdSetColor(ALARM_COLOR_INDEX); + lcdSetColor(lcdColorTable[ALARM_COLOR_INDEX]); } drawSource(x+NUMBERS_PADDING, y+2, field, CUSTOM_COLOR); drawSource(x+NUMBERS_PADDING + 1, y + 3, field, BLACK); @@ -108,7 +108,7 @@ void ValueWidget::refresh() if (field >= MIXSRC_FIRST_TELEM) { TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index if (!telemetryItem.isAvailable() || telemetryItem.isOld()) { - lcdSetColor(ALARM_COLOR_INDEX); + lcdSetColor(lcdColorTable[TEXT_DISABLE_COLOR_INDEX]); } } diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index af7dda379..c29c71e6b 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -80,7 +80,7 @@ class WidgetsContainer: public WidgetsContainerInterface } } - virtual void createWidget(unsigned int index, const WidgetFactory * factory) + void createWidget(unsigned int index, const WidgetFactory * factory) override { if (widgets) { memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName)); @@ -123,9 +123,9 @@ class WidgetsContainer: public WidgetsContainerInterface return &persistentData->options[index].value; } - virtual unsigned int getZonesCount() const = 0; + unsigned int getZonesCount() const override = 0; - virtual Zone getZone(unsigned int index) const = 0; + Zone getZone(unsigned int index) const override = 0; virtual void refresh() { diff --git a/radio/src/gui/common/stdlcd/draw_functions.cpp b/radio/src/gui/common/stdlcd/draw_functions.cpp index 155450fc3..bce732dae 100644 --- a/radio/src/gui/common/stdlcd/draw_functions.cpp +++ b/radio/src/gui/common/stdlcd/draw_functions.cpp @@ -390,6 +390,11 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value, return; } + if (IS_FAI_FORBIDDEN(MIXSRC_FIRST_TELEM + 3 * sensor)) { + lcdDrawText(x, y, "FAI mode", flags); + return; + } + TelemetryItem & telemetryItem = telemetryItems[sensor]; TelemetrySensor & telemetrySensor = g_model.telemetrySensors[sensor]; @@ -434,6 +439,10 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value, "Rx2 Lost", "Rx1 NS", "Rx2 NS", + "Rx3 FS", + "Rx3 LF", + "Rx3 Lost", + "Rx3 NS" }; for (uint8_t i = 0; i < DIM(RXS_STATUS); i++) { if (value & (1u << i)) { diff --git a/radio/src/gui/common/stdlcd/draw_functions.h b/radio/src/gui/common/stdlcd/draw_functions.h index 5cbc9c271..5b61dde6b 100644 --- a/radio/src/gui/common/stdlcd/draw_functions.h +++ b/radio/src/gui/common/stdlcd/draw_functions.h @@ -47,4 +47,9 @@ void drawSleepBitmap(); void lcdDrawMMM(coord_t x, coord_t y, LcdFlags flags=0); void drawTrimMode(coord_t x, coord_t y, uint8_t flightMode, uint8_t idx, LcdFlags att=0); +typedef int (*FnFuncP) (int x); +void drawFunction(FnFuncP fn, uint8_t offset = 0); +void drawCursor(FnFuncP fn, uint8_t offset = 0); +void drawCurve(coord_t offset = 0); + #endif // _STDLCD_DRAW_FUNCTIONS_H_ diff --git a/radio/src/gui/common/stdlcd/model_curves.cpp b/radio/src/gui/common/stdlcd/model_curves.cpp index 659e8beae..2b3c3cb07 100644 --- a/radio/src/gui/common/stdlcd/model_curves.cpp +++ b/radio/src/gui/common/stdlcd/model_curves.cpp @@ -62,6 +62,7 @@ void menuModelCurvesAll(event_t event) case EVT_KEY_FIRST(KEY_ENTER): if (CURVE_SELECTED() && !READ_ONLY()) { s_currIdxSubMenu = sub; + s_currSrcRaw = MIXSRC_NONE; pushMenu(menuModelCurveOne); } break; @@ -141,9 +142,9 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag break; case CURVE_REF_CUSTOM: drawCurveName(x, y, curve.value, flags); - if (active && menuHorizontalPosition==1) { - if (event==EVT_KEY_LONG(KEY_ENTER) && curve.value!=0) { - s_currIdxSubMenu = (curve.value<0 ? -curve.value-1 : curve.value-1); + if (active && menuHorizontalPosition == 1) { + if (event == EVT_KEY_LONG(KEY_ENTER) && curve.value != 0) { + s_currIdxSubMenu = abs(curve.value) - 1; pushMenu(menuModelCurveOne); } else { @@ -153,3 +154,48 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag break; } } + +void drawFunction(FnFuncP fn, uint8_t offset) +{ + lcdDrawVerticalLine(CURVE_CENTER_X - offset, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, CURVE_SIDE_WIDTH * 2, 0xee); + lcdDrawHorizontalLine(CURVE_CENTER_X - CURVE_SIDE_WIDTH - offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH * 2, 0xee); + + coord_t prev_yv = (coord_t) - 1; + + for (int xv = -CURVE_SIDE_WIDTH; xv <= CURVE_SIDE_WIDTH; xv++) { + coord_t yv = (LCD_H - 1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H - 1) / RESX); + if (prev_yv != (coord_t) - 1) { + if (abs((int8_t)yv-prev_yv) <= 1) { + lcdDrawPoint(CURVE_CENTER_X + xv - offset - 1, prev_yv, FORCE); + } + else { + uint8_t tmp = (prev_yv < yv ? 0 : 1); + lcdDrawSolidVerticalLine(CURVE_CENTER_X + xv - offset - 1, yv + tmp, prev_yv - yv); + } + } + prev_yv = yv; + } +} + +void drawCursor(FnFuncP fn, uint8_t offset) +{ + int x512 = getValue(s_currSrcRaw); + if (s_currSrcRaw >= MIXSRC_FIRST_TELEM) { + if (s_currScale > 0) + x512 = (x512 * 1024) / convertTelemValue(s_currSrcRaw - MIXSRC_FIRST_TELEM + 1, s_currScale); + drawSensorCustomValue(LCD_W - FW - offset, 6 * FH, (s_currSrcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); + } + else { + lcdDrawNumber(LCD_W - FW - offset, 6*FH, calcRESXto1000(x512), RIGHT | PREC1); + } + x512 = limit(-1024, x512, 1024); + int y512 = fn(x512); + y512 = limit(-1024, y512, 1024); + lcdDrawNumber(CURVE_CENTER_X - FWNUM - offset, 1*FH, calcRESXto1000(y512), RIGHT | PREC1); + + x512 = CURVE_CENTER_X + x512/(RESX / CURVE_SIDE_WIDTH); + y512 = (LCD_H - 1) - ((y512 + RESX) / 2) * (LCD_H - 1) / RESX; + + lcdDrawSolidVerticalLine(x512 - offset, y512-3, 3 * 2 + 1); + lcdDrawSolidHorizontalLine(x512 - 3 - offset, y512, 3 * 2 + 1); +} diff --git a/radio/src/gui/common/stdlcd/model_receiver_options.cpp b/radio/src/gui/common/stdlcd/model_receiver_options.cpp index 6ce66ee29..de3547b75 100644 --- a/radio/src/gui/common/stdlcd/model_receiver_options.cpp +++ b/radio/src/gui/common/stdlcd/model_receiver_options.cpp @@ -48,6 +48,7 @@ enum { ITEM_RECEIVER_SETTINGS_TELEMETRY, ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW, ITEM_RECEIVER_SETTINGS_SPORT_FPORT, + ITEM_RECEIVER_SETTINGS_FPORT2, ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1, ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2, ITEM_RECEIVER_SETTINGS_PINMAP_FIRST @@ -82,6 +83,7 @@ void menuModelReceiverOptions(event_t event) isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // Telemetry IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0), IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT, 0), + IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT2, 0), uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), 0 // channels ... @@ -171,6 +173,13 @@ void menuModelReceiverOptions(event_t event) } break; + case ITEM_RECEIVER_SETTINGS_FPORT2: + reusableBuffer.hardwareAndSettings.receiverSettings.fport2 = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport2, RECEIVER_OPTIONS_2ND_COLUMN, y, "F.Port2", attr, event); + if (attr && checkIncDec_Ret) { + reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY; + } + break; + case ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1: lcdDrawText(LCD_W/2, y+1, STR_MORE_OPTIONS_AVAILABLE, SMLSIZE|CENTERED); break; diff --git a/radio/src/gui/common/stdlcd/model_setup_afhds3.cpp b/radio/src/gui/common/stdlcd/model_setup_afhds3.cpp new file mode 100644 index 000000000..a094ef83a --- /dev/null +++ b/radio/src/gui/common/stdlcd/model_setup_afhds3.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +void onBindMenuAfhds3(const char * result) +{ + uint8_t moduleIdx = CURRENT_MODULE_EDITED(menuVerticalPosition - HEADER_LINE); + + if (result == STR_AFHDS3_ONE_TO_ONE_TELEMETRY) { + g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry = 1; + } + else if (result == STR_AFHDS3_ONE_TO_MANY) { + g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry = 0; + } + else { + return; + } + + moduleState[moduleIdx].mode = MODULE_MODE_BIND; +} + +void startBindMenuAfhds3(uint8_t moduleIdx) +{ + uint8_t selection = 0; +#if defined(AFHDS3) + POPUP_MENU_ADD_ITEM(STR_AFHDS3_ONE_TO_ONE_TELEMETRY); + POPUP_MENU_ADD_ITEM(STR_AFHDS3_ONE_TO_MANY); +#endif + POPUP_MENU_SELECT_ITEM(selection); + POPUP_MENU_START(onBindMenuAfhds3); +} diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index ddeccb348..caedaa074 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -162,7 +162,7 @@ enum { ITEM_RADIO_HARDWARE_CAPACITY_CALIB, #endif -#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 +#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000 ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE, #endif @@ -278,7 +278,7 @@ void onHardwareAntennaSwitchConfirm(const char * result) #define TX_CAPACITY_MEASUREMENT_ROWS #endif -#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 +#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000 #define MAX_BAUD_ROWS 0, #else #define MAX_BAUD_ROWS @@ -292,7 +292,7 @@ void onHardwareAntennaSwitchConfirm(const char * result) #if LCD_W >= 212 #define HW_SETTINGS_COLUMN1 12*FW - #define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 6*FW) + #define HW_SETTINGS_COLUMN2 (20*FW - 3) #else #define HW_SETTINGS_COLUMN1 30 #define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 5*FW) @@ -544,7 +544,7 @@ void menuRadioHardware(event_t event) break; #endif -#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 +#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000 case ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE: lcdDrawTextAlignedLeft(y, STR_MAXBAUDRATE); lcdDrawNumber(HW_SETTINGS_COLUMN2, y, CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate], attr|LEFT); @@ -569,7 +569,7 @@ void menuRadioHardware(event_t event) lcdDrawTextAlignedLeft(y, STR_BLUETOOTH); lcdDrawTextAtIndex(HW_SETTINGS_COLUMN2, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, attr); if (attr) { - g_eeGeneral.bluetoothMode = checkIncDecGen(event, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER); + g_eeGeneral.bluetoothMode = checkIncDecGen(event, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_MAX); } break; diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp index 80c2f7207..b07eee74d 100644 --- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp +++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp @@ -251,10 +251,16 @@ void onSdManagerMenu(const char * result) } #endif #if defined(PXX2) - else if (result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL || result == STR_FLASH_RECEIVER_OTA_BY_EXTERNAL) { + else if (result == STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA || result == STR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA) { memclear(&reusableBuffer.sdManager.otaUpdateInformation, sizeof(OtaUpdateInformation)); getSelectionFullPath(reusableBuffer.sdManager.otaUpdateInformation.filename); - reusableBuffer.sdManager.otaUpdateInformation.module = result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL ? INTERNAL_MODULE : EXTERNAL_MODULE; + reusableBuffer.sdManager.otaUpdateInformation.module = (result == STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA ? INTERNAL_MODULE : EXTERNAL_MODULE); + moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged); + } + else if (result == STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA || result == STR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA) { + memclear(&reusableBuffer.sdManager.otaUpdateInformation, sizeof(OtaUpdateInformation)); + getSelectionFullPath(reusableBuffer.sdManager.otaUpdateInformation.filename); + reusableBuffer.sdManager.otaUpdateInformation.module = (result == STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA ? INTERNAL_MODULE : EXTERNAL_MODULE); moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged); } #endif @@ -408,14 +414,18 @@ void menuRadioSdManager(event_t _event) else if (!READ_ONLY() && !strcasecmp(ext, SPORT_FIRMWARE_EXT)) { if (HAS_SPORT_UPDATE_CONNECTOR()) POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE); +#if defined(INTERNAL_MODULE_PXX1) || defined(INTERNAL_MODULE_PXX2) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); +#endif POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE); } else if (!READ_ONLY() && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) { FrSkyFirmwareInformation information; if (readFrSkyFirmwareInformation(line, information) == nullptr) { +#if defined(INTERNAL_MODULE_PXX1) || defined(INTERNAL_MODULE_PXX2) if (information.productFamily == FIRMWARE_FAMILY_INTERNAL_MODULE) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); +#endif if (information.productFamily == FIRMWARE_FAMILY_EXTERNAL_MODULE) POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE); if (information.productFamily == FIRMWARE_FAMILY_RECEIVER || information.productFamily == FIRMWARE_FAMILY_SENSOR) { @@ -427,9 +437,13 @@ void menuRadioSdManager(event_t _event) #if defined(PXX2) if (information.productFamily == FIRMWARE_FAMILY_RECEIVER) { if (isReceiverOTAEnabledFromModule(INTERNAL_MODULE, information.productId)) - POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_INTERNAL); + POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA); if (isReceiverOTAEnabledFromModule(EXTERNAL_MODULE, information.productId)) - POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_EXTERNAL); + POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA); + } + if (information.productFamily == FIRMWARE_FAMILY_FLIGHT_CONTROLLER) { + POPUP_MENU_ADD_ITEM(STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA); + POPUP_MENU_ADD_ITEM(STR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA); } #endif #if defined(BLUETOOTH) diff --git a/radio/src/gui/common/stdlcd/radio_version.cpp b/radio/src/gui/common/stdlcd/radio_version.cpp index ce6e30e59..d6128ecb7 100644 --- a/radio/src/gui/common/stdlcd/radio_version.cpp +++ b/radio/src/gui/common/stdlcd/radio_version.cpp @@ -222,7 +222,7 @@ void menuRadioModulesVersion(event_t event) enum MenuRadioVersionItems { ITEM_RADIO_VERSION_FIRST = HEADER_LINE - 1, -#if defined(PCBTARANIS) || defined(PCBHORUS) +#if defined(PCBTARANIS) ITEM_RADIO_FIRMWARE_OPTIONS, #endif #if defined(PXX2) @@ -250,7 +250,7 @@ void menuRadioVersion(event_t event) y += 2; -#if defined(PCBTARANIS) || defined(PCBHORUS) +#if defined(PCBTARANIS) lcdDrawText(INDENT_WIDTH, y, BUTTON(TR_FIRMWARE_OPTIONS), menuVerticalPosition == ITEM_RADIO_FIRMWARE_OPTIONS ? INVERS : 0); y += FH; if (menuVerticalPosition == ITEM_RADIO_FIRMWARE_OPTIONS && event == EVT_KEY_BREAK(KEY_ENTER)) { diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index fbc3073b4..76af36527 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -387,6 +387,32 @@ bool isSwitchAvailable(int swtch, SwitchContext context) return true; } +bool isAux1ModeAvailable(int mode) +{ +#if defined(AUX2_SERIAL) + if (mode == UART_MODE_SBUS_TRAINER) + return g_eeGeneral.aux2SerialMode != UART_MODE_SBUS_TRAINER; +#if defined(RADIO_TX16S) + else + return (g_model.trainerData.mode != TRAINER_MODE_MASTER_BATTERY_COMPARTMENT || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER); +#endif +#endif + return true; +} + +bool isAux2ModeAvailable(int mode) +{ +#if defined(AUX_SERIAL) + if (mode == UART_MODE_SBUS_TRAINER) + return g_eeGeneral.auxSerialMode != UART_MODE_SBUS_TRAINER; +#if defined(RADIO_TX16S) + else + return (g_model.trainerData.mode != TRAINER_MODE_MASTER_BATTERY_COMPARTMENT || g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER); +#endif +#endif + return true; +} + bool isSwitchAvailableInLogicalSwitches(int swtch) { return isSwitchAvailable(swtch, LogicalSwitchesContext); @@ -552,6 +578,7 @@ bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType) case MODULE_TYPE_ISRM_PXX2: case MODULE_TYPE_R9M_LITE_PXX2: case MODULE_TYPE_R9M_LITE_PRO_PXX2: + case MODULE_TYPE_AFHDS3: return false; case MODULE_TYPE_XJT_PXX1: @@ -566,17 +593,20 @@ bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType) } } +bool areModulesConflicting(int intModuleType, int extModuleType) +{ + if (intModuleType == MODULE_TYPE_ISRM_PXX2) + return (extModuleType == MODULE_TYPE_GHOST); + + return false; +} + #if defined(HARDWARE_INTERNAL_MODULE) bool isInternalModuleAvailable(int moduleType) { if (moduleType == MODULE_TYPE_NONE) return true; -#if defined(PCBNV14) - if (moduleType == MODULE_TYPE_FLYSKY) - return true; -#endif - #if defined(INTERNAL_MODULE_MULTI) if (moduleType == MODULE_TYPE_MULTIMODULE) return true; @@ -592,7 +622,7 @@ bool isInternalModuleAvailable(int moduleType) if (moduleType == MODULE_TYPE_ISRM_PXX2) { #if defined(PXX2) && defined(INTERNAL_MODULE_PXX2) - return true; + return !areModulesConflicting(moduleType, g_model.moduleData[EXTERNAL_MODULE].type); #endif } @@ -612,12 +642,6 @@ bool isInternalModuleAvailable(int moduleType) bool isExternalModuleAvailable(int moduleType) { - if (moduleType == MODULE_TYPE_FLYSKY) - return false; // doesn't exist for now - - if (moduleType == MODULE_TYPE_R9M_LITE_PRO_PXX1) - return false; - #if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) if (isModuleTypeR9MLite(moduleType) || moduleType == MODULE_TYPE_XJT_LITE_PXX2) return false; @@ -653,6 +677,11 @@ bool isExternalModuleAvailable(int moduleType) return false; #endif +#if !defined(GHOST) + if (moduleType == MODULE_TYPE_GHOST) + return false; +#endif + #if !defined(DSM2) if (moduleType == MODULE_TYPE_DSM2) return false; @@ -669,6 +698,9 @@ bool isExternalModuleAvailable(int moduleType) #endif #if defined(HARDWARE_INTERNAL_MODULE) + if (areModulesConflicting(g_model.moduleData[INTERNAL_MODULE].type, moduleType)) + return false; + if (isTrainerUsingModuleBay() || (isModuleUsingSport(EXTERNAL_MODULE, moduleType) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type))) return false; #endif @@ -678,6 +710,11 @@ bool isExternalModuleAvailable(int moduleType) return false; #endif +#if !defined(AFHDS3) + if (moduleType == MODULE_TYPE_AFHDS3) + return false; +#endif + return true; } @@ -688,6 +725,11 @@ bool isRfProtocolAvailable(int protocol) return false; } #endif +#if defined(GHOST) + if (protocol != MODULE_SUBTYPE_PXX1_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST) { + return false; + } +#endif #if !defined(MODULE_PROTOCOL_D8) if (protocol == MODULE_SUBTYPE_PXX1_ACCST_D8) { return false; @@ -717,12 +759,22 @@ bool isTelemetryProtocolAvailable(int protocol) return false; } + if ( protocol== PROTOCOL_TELEMETRY_GHOST) { + return false; + } + #if !defined(MULTIMODULE) if (protocol == PROTOCOL_TELEMETRY_SPEKTRUM || protocol == PROTOCOL_TELEMETRY_FLYSKY_IBUS || protocol == PROTOCOL_TELEMETRY_MULTIMODULE) { return false; } #endif +#if !defined(AFHDS3) + if (protocol == PROTOCOL_TELEMETRY_AFHDS3) { + return false; + } +#endif + #if defined(PCBHORUS) if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) { return false; @@ -746,7 +798,10 @@ bool isTrainerModeAvailable(int mode) } #endif -#if defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT) +#if defined(RADIO_TX16S) + if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) + return (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER); +#elif defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT) if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) return false; #elif defined(PCBTARANIS) @@ -790,6 +845,25 @@ bool modelHasNotes() return false; } +bool confirmModelChange() +{ + if (TELEMETRY_STREAMING()) { + RAISE_ALERT(STR_MODEL, STR_MODEL_STILL_POWERED, STR_PRESS_ENTER_TO_CONFIRM, AU_MODEL_STILL_POWERED); + while (TELEMETRY_STREAMING()) { + RTOS_WAIT_MS(20); + if (readKeys() == (1 << KEY_ENTER)) { + killEvents(KEY_ENTER); + return true; + } + else if (readKeys() == (1 << KEY_EXIT)) { + killEvents(KEY_EXIT); + return false; + } + } + } + return true; +} + int getFirstAvailable(int min, int max, IsValueAvailable isValueAvailable) { int retval = 0; @@ -869,8 +943,8 @@ const char STR_SUBTYPE_FLYSKY[] = "\004""Std\0""V9x9""V6x6""V912""CX20"; const char STR_SUBTYPE_HUBSAN[] = "\004""H107""H301""H501"; const char STR_SUBTYPE_FRSKY[] = "\011""D16\0 ""D8\0 ""D16 8ch\0 ""V8\0 ""LBT(EU)\0 ""LBT 8ch\0 ""D8Cloned\0""D16Cloned"; const char STR_SUBTYPE_HISKY[] = "\005""Std\0 ""HK310"; -const char STR_SUBTYPE_V2X2[] = "\006""Std\0 ""JXD506"; -const char STR_SUBTYPE_DSM[] = "\006""2 22ms""2 11ms""X 22ms""X 11ms"; +const char STR_SUBTYPE_V2X2[] = "\006""Std\0 ""JXD506""MR101\0"; +const char STR_SUBTYPE_DSM[] = "\004""2 1F""2 2F""X 1F""X 2F"; const char STR_SUBTYPE_DEVO[] = "\004""8ch\0""10ch""12ch""6ch\0""7ch\0"; const char STR_SUBTYPE_YD717[] = "\007""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 "; const char STR_SUBTYPE_KN[] = "\006""WLtoys""FeiLun"; @@ -899,6 +973,7 @@ const char STR_SUBTYPE_TRAXXAS[] = "\004""6519"; const char STR_SUBTYPE_E01X[] = "\005""E012\0""E015\0""E016H"; const char STR_SUBTYPE_V911S[] = "\004""Std\0""E119"; const char STR_SUBTYPE_GD00X[] = "\005""GD_V1""GD_V2"; +const char STR_SUBTYPE_V761[] = "\003""3ch""4ch"; const char STR_SUBTYPE_REDPINE[] = "\004""Fast""Slow"; const char STR_SUBTYPE_POTENSIC[] = "\003""A20"; const char STR_SUBTYPE_ZSX[] = "\007""280JJRC"; @@ -908,7 +983,7 @@ const char STR_SUBTYPE_HOTT[] = "\007""Sync\0 ""No_Sync"; const char STR_SUBTYPE_FX816[] = "\003""P38"; const char STR_SUBTYPE_PELIKAN[] = "\004""Pro\0""Lite"; const char STR_SUBTYPE_XK[] = "\004""X450""X420"; -const char STR_SUBTYPE_XN297DUMP[] = "\004""250K""1M\0 ""2M\0 ""AUTO"; +const char STR_SUBTYPE_XN297DUMP[] = "\004""250K""1M\0 ""2M\0 ""AUTO""NRF\0"; const char STR_SUBTYPE_FRSKYX2[] = "\011""D16\0 ""D16 8ch\0 ""LBT(EU)\0 ""LBT 8ch\0 ""D16Cloned"; const char STR_SUBTYPE_FRSKYR9[] = "\007""915MHz\0""868MHz\0""915 8ch""868 8ch"; const char STR_SUBTYPE_PROPEL[] = "\004""74-Z"; @@ -924,7 +999,8 @@ const char* mm_options_strings::options[] = { STR_MULTI_TELEMETRY, STR_MULTI_SERVOFREQ, STR_MULTI_MAX_THROW, - STR_MULTI_RFCHAN + STR_MULTI_RFCHAN, + STR_MULTI_RFPOWER }; const mm_protocol_definition multi_protocols[] = { @@ -933,7 +1009,7 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ}, {MODULE_SUBTYPE_MULTI_FRSKY, 7, false, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_HISKY, 1, false, true, STR_SUBTYPE_HISKY, nullptr}, - {MODULE_SUBTYPE_MULTI_V2X2, 1, false, false, STR_SUBTYPE_V2X2, nullptr}, + {MODULE_SUBTYPE_MULTI_V2X2, 2, false, false, STR_SUBTYPE_V2X2, nullptr}, {MODULE_SUBTYPE_MULTI_DSM2, 3, false, true, STR_SUBTYPE_DSM, STR_MULTI_MAX_THROW}, {MODULE_SUBTYPE_MULTI_DEVO, 4, false, true, STR_SUBTYPE_DEVO, STR_MULTI_FIXEDID}, {MODULE_SUBTYPE_MULTI_YD717, 4, false, false, STR_SUBTYPE_YD717, nullptr}, @@ -966,6 +1042,7 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_E01X, 2, false, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION}, {MODULE_SUBTYPE_MULTI_V911S, 1, false, false, STR_SUBTYPE_V911S, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_GD00X, 1, false, false, STR_SUBTYPE_GD00X, STR_MULTI_RFTUNE}, + {MODULE_SUBTYPE_MULTI_V761, 1, false, false, STR_SUBTYPE_V761, nullptr}, {MODULE_SUBTYPE_MULTI_KF606, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_REDPINE, 1, false, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, false, STR_SUBTYPE_POTENSIC, nullptr}, @@ -976,7 +1053,7 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_FX816, 0, false, false, STR_SUBTYPE_FX816, nullptr}, {MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, false, STR_SUBTYPE_PELIKAN, nullptr}, {MODULE_SUBTYPE_MULTI_XK, 1, false, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE}, - {MODULE_SUBTYPE_MULTI_XN297DUMP, 3, false, false, STR_SUBTYPE_XN297DUMP, STR_MULTI_RFCHAN}, + {MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, false, STR_SUBTYPE_XN297DUMP, STR_MULTI_RFCHAN}, {MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, false, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, false, STR_SUBTYPE_FRSKYR9, nullptr}, {MODULE_SUBTYPE_MULTI_PROPEL, 0, false, false, STR_SUBTYPE_PROPEL, nullptr}, diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 493d08339..c1968960c 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -85,6 +85,8 @@ bool isSourceAvailableInCustomSwitches(int source); bool isSourceAvailableInResetSpecialFunction(int index); bool isSourceAvailableInGlobalResetSpecialFunction(int index); bool isSwitchAvailable(int swtch, SwitchContext context); +bool isAux1ModeAvailable(int mode); +bool isAux2ModeAvailable(int mode); bool isSwitchAvailableInLogicalSwitches(int swtch); bool isSwitchAvailableInCustomFunctions(int swtch); bool isSwitchAvailableInMixes(int swtch); @@ -114,6 +116,8 @@ bool isRssiSensorAvailable(int sensor); bool modelHasNotes(); +bool confirmModelChange(); + #if defined(COLORLCD) bool isSwitch2POSWarningStateAvailable(int state); #endif @@ -128,6 +132,7 @@ bool isSwitch2POSWarningStateAvailable(int state); swsrc_t checkIncDecMovedSwitch(swsrc_t val); +// TODO move this to stdlcd/draw_functions.h ? void drawCurveRef(coord_t x, coord_t y, CurveRef & curve, LcdFlags flags=0); void drawDate(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags flags=0); void drawTelemScreenDate(coord_t x, coord_t y, source_t sensor, LcdFlags flags=0); @@ -139,21 +144,22 @@ void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0); int convertMultiToOtx(int type); -void drawCurve(coord_t offset=0); - // model_setup Defines that are used in all uis in the same way #define IF_INTERNAL_MODULE_ON(x) (IS_INTERNAL_MODULE_ENABLED() ? (uint8_t)(x) : HIDDEN_ROW) #define IF_MODULE_ON(moduleIndex, x) (IS_MODULE_ENABLED(moduleIndex) ? (uint8_t)(x) : HIDDEN_ROW) inline uint8_t MODULE_BIND_ROWS(int moduleIdx) { + if (isModuleCrossfire(moduleIdx)) + return 0; + if (isModuleMultimodule(moduleIdx)) { - if (IS_RX_MULTI(moduleIdx)) - return 1; - else - return 2; + if (IS_RX_MULTI(moduleIdx)) + return 1; + else + return 2; } - else if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx)) { + else if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx) || isModuleAFHDS3(moduleIdx)) { return 1; } else if (isModulePPM(moduleIdx) || isModulePXX1(moduleIdx) || isModulePXX2(moduleIdx) || isModuleDSM2(moduleIdx)) { @@ -177,7 +183,7 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) else return 0; } - else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleSBUS(moduleIdx)) { + else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleGhost(moduleIdx) || isModuleSBUS(moduleIdx)) { return 0; } else { @@ -282,9 +288,10 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx) #define MULTIMODULE_TYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, #define MULTIMODULE_SUBTYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW, #define MULTIMODULE_OPTIONS_ROW(moduleIdx) (isModuleMultimodule(moduleIdx) && MULTIMODULE_HASOPTIONS(moduleIdx)) ? (uint8_t) 0: HIDDEN_ROW -#define MODULE_POWER_ROW(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) || isModuleR9MNonAccess(moduleIdx)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW +#define MODULE_POWER_ROW(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleAFHDS3(moduleIdx)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW #else +#define MULTIMODULE_TYPE_ROWS(moduleIdx) #define MULTIMODULE_STATUS_ROWS(moduleIdx) #define MULTIMODULE_MODULE_ROWS(moduleIdx) #define MULTIMODULE_TYPE_ROW(moduleIdx) @@ -292,11 +299,28 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx) #define MULTIMODULE_TYPE_ROWS(moduleIdx) #define MULTIMODULE_MODE_ROWS(moduleIdx) (uint8_t)0 #define MULTIMODULE_OPTIONS_ROW(moduleIdx) HIDDEN_ROW -#define MODULE_POWER_ROW(moduleIdx) isModuleR9MNonAccess(moduleIdx) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW +#define MODULE_POWER_ROW(moduleIdx) isModuleR9MNonAccess(moduleIdx) || isModuleAFHDS3(moduleIdx) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW +#endif + +#if defined(AFHDS3) +#define AFHDS3_PROTOCOL_ROW(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, +#define AFHDS3_MODE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, +#define AFHDS3_MODULE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? (uint8_t) TITLE_ROW : HIDDEN_ROW, +#else +#define AFHDS3_PROTOCOL_ROW(moduleIdx) +#define AFHDS3_MODE_ROWS(moduleIdx) +#define AFHDS3_MODULE_ROWS(moduleIdx) #endif #define FAILSAFE_ROWS(moduleIdx) isModuleFailsafeAvailable(moduleIdx) ? (g_model.moduleData[moduleIdx].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW -#define MODULE_OPTION_ROW(moduleIdx) (isModuleR9MNonAccess(moduleIdx) || isModuleSBUS(moduleIdx) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW(moduleIdx)) + +inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) { + if(isModuleR9MNonAccess(moduleIdx) || isModuleSBUS(moduleIdx)) + return TITLE_ROW; + if(isModuleAFHDS3(moduleIdx)) + return HIDDEN_ROW; + return MULTIMODULE_OPTIONS_ROW(moduleIdx); +} void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags); diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 43dac1678..fdb230f47 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -161,7 +161,7 @@ const uint8_t * FrskyDeviceFirmwareUpdate::readFullDuplexFrame(ModuleFifo & fifo const uint8_t * FrskyDeviceFirmwareUpdate::readHalfDuplexFrame(uint32_t timeout) { - for (int i=timeout; i>=0; i--) { + for (int i = timeout; i >= 0; i--) { uint8_t byte ; while (telemetryGetByte(&byte)) { if (pushFrskyTelemetryData(byte)) { @@ -488,7 +488,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename, Pro uint8_t extPwr = IS_EXTERNAL_MODULE_ON(); EXTERNAL_MODULE_OFF(); -#if HAS_SPORT_UPDATE_CONNECTOR() +#if defined(SPORT_UPDATE_PWR_GPIO) uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON(); SPORT_UPDATE_POWER_OFF(); #endif @@ -534,7 +534,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename, Pro setupPulsesExternalModule(); } -#if HAS_SPORT_UPDATE_CONNECTOR() +#if defined(SPORT_UPDATE_PWR_GPIO) if (spuPwr) { SPORT_UPDATE_POWER_ON(); } @@ -761,7 +761,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, Progr uint8_t extPwr = IS_EXTERNAL_MODULE_ON(); EXTERNAL_MODULE_OFF(); -#if HAS_SPORT_UPDATE_CONNECTOR() +#if defined(SPORT_UPDATE_PWR_GPIO) uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON(); SPORT_UPDATE_POWER_OFF(); #endif @@ -802,7 +802,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, Progr setupPulsesExternalModule(); } -#if HAS_SPORT_UPDATE_CONNECTOR() +#if defined(SPORT_UPDATE_PWR_GPIO) if (spuPwr) { SPORT_UPDATE_POWER_ON(); } diff --git a/radio/src/io/frsky_firmware_update.h b/radio/src/io/frsky_firmware_update.h index 16b99e224..a6750d2cf 100644 --- a/radio/src/io/frsky_firmware_update.h +++ b/radio/src/io/frsky_firmware_update.h @@ -35,6 +35,7 @@ enum FrskyFirmwareProductFamily { FIRMWARE_FAMILY_SENSOR, FIRMWARE_FAMILY_BLUETOOTH_CHIP, FIRMWARE_FAMILY_POWER_MANAGEMENT_UNIT, + FIRMWARE_FAMILY_FLIGHT_CONTROLLER, }; enum FrskyFirmwareModuleProductId { diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index ee89017d0..21dc934e1 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -534,7 +534,7 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan uint8_t extPwr = IS_EXTERNAL_MODULE_ON(); EXTERNAL_MODULE_OFF(); -#if HAS_SPORT_UPDATE_CONNECTOR() +#if defined(SPORT_UPDATE_PWR_GPIO) uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON(); SPORT_UPDATE_POWER_OFF(); #endif @@ -583,7 +583,7 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan setupPulsesExternalModule(); } -#if HAS_SPORT_UPDATE_CONNECTOR() +#if defined(SPORT_UPDATE_PWR_GPIO) if (spuPwr) { SPORT_UPDATE_POWER_ON(); } diff --git a/radio/src/io/multi_firmware_update.h b/radio/src/io/multi_firmware_update.h index 100b9012d..00dd5588f 100644 --- a/radio/src/io/multi_firmware_update.h +++ b/radio/src/io/multi_firmware_update.h @@ -76,7 +76,7 @@ class MultiFirmwareInformation { bool isMultiExternalFirmware() const { - return (telemetryInversion == true && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY); + return ((telemetryInversion == true || boardType == FIRMWARE_MULTI_STM ) && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY); } const char * readMultiFirmwareInformation(const char * filename); diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index a2556453e..b5fba0dc6 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -375,6 +375,26 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags) return false; // not found } +/*luadoc +@function getRotEncSpeed() + +Return rotary encoder current speed + +@retval number in list: ROTENC_LOWSPEED, ROTENC_MIDSPEED, ROTENC_HIGHSPEED + return 0 on radio without rotary encoder + +@status current Introduced in 2.3.10 +*/ +static int luaGetRotEncSpeed(lua_State * L) +{ +#if defined(ROTARY_ENCODER_NAVIGATION) + lua_pushunsigned(L, rotencSpeed); +#else + lua_pushunsigned(L, 0); +#endif + return 1; +} + /*luadoc @function sportTelemetryPop() @@ -847,7 +867,7 @@ Return the internal GPS position or nil if no valid hardware found static int luaGetTxGPS(lua_State * L) { #if defined(INTERNAL_GPS) - lua_createtable(L, 0, 7); + lua_createtable(L, 0, 8); lua_pushtablenumber(L, "lat", gpsData.latitude * 0.000001); lua_pushtablenumber(L, "lon", gpsData.longitude * 0.000001); lua_pushtableinteger(L, "numsat", gpsData.numSat); @@ -1680,6 +1700,7 @@ const luaL_Reg opentxLib[] = { { "getVersion", luaGetVersion }, { "getGeneralSettings", luaGetGeneralSettings }, { "getGlobalTimer", luaGetGlobalTimer }, + { "getRotEncSpeed", luaGetRotEncSpeed }, { "getValue", luaGetValue }, { "getRAS", luaGetRAS }, { "getTxGPS", luaGetTxGPS }, @@ -1742,6 +1763,7 @@ const luaR_value_entry opentxConstants[] = { { "VALUE", INPUT_TYPE_VALUE }, { "SOURCE", INPUT_TYPE_SOURCE }, { "REPLACE", MLTPX_REP }, + { "MIXSRC_MAX", MIXSRC_MAX }, { "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT }, { "MIXSRC_Rud", MIXSRC_Rud }, { "MIXSRC_Ele", MIXSRC_Ele }, @@ -1813,6 +1835,9 @@ const luaR_value_entry opentxConstants[] = { { "EVT_VIRTUAL_NEXT", EVT_ROTARY_RIGHT }, { "EVT_VIRTUAL_DEC", EVT_ROTARY_LEFT }, { "EVT_VIRTUAL_INC", EVT_ROTARY_RIGHT }, + { "ROTENC_LOWSPEED", ROTENC_LOWSPEED }, + { "ROTENC_MIDSPEED", ROTENC_MIDSPEED }, + { "ROTENC_HIGHSPEED", ROTENC_HIGHSPEED }, #elif defined(PCBX9D) || defined(PCBX9DP) // key reverted between field nav and value change { "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_PLUS) }, { "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_PLUS) }, @@ -1980,6 +2005,9 @@ const luaR_value_entry opentxConstants[] = { {"UNIT_MILLILITERS", UNIT_MILLILITERS }, {"UNIT_FLOZ", UNIT_FLOZ }, {"UNIT_MILLILITERS_PER_MINUTE", UNIT_MILLILITERS_PER_MINUTE }, + {"UNIT_HERTZ", UNIT_HERTZ }, + {"UNIT_MS", UNIT_MS }, + {"UNIT_US", UNIT_US }, {"UNIT_HOURS", UNIT_HOURS }, {"UNIT_MINUTES", UNIT_MINUTES }, {"UNIT_SECONDS", UNIT_SECONDS }, diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp index d2d5f767a..9e9aa310c 100644 --- a/radio/src/lua/api_model.cpp +++ b/radio/src/lua/api_model.cpp @@ -363,6 +363,136 @@ static int luaModelGetInputsCount(lua_State *L) return 1; } +/*luadoc +@function model.deleteFlightModes() + +Clear all flightModes + +@status current Introduced in 2.3.10 +*/ +static int luaModelDeleteFlightModes(lua_State *L) +{ + memset(g_model.flightModeData, 0, sizeof(g_model.flightModeData)); + return 0; +} + +/*luadoc +@function model.getFlightMode(index) + +@param index (unsigned number) flight mode number (use 0 for FM0) + +Return input data for given input and line number + +@retval nil requested input or line does not exist + +@retval table input data: + * `name` (string) input line name + * `switch` (number) input switch index + * `fadeIn` (number) fade in value (in 0.1s) + * `fadeOut` (number) fade out value (in 0.1s) + * `trimsValues` (table) table of trim values: + * `key` is trim number (zero based) + * `value` is trim value + * `trimsModes` (table) table of trim mode: + * `key` is trim number (zero based) + * `value` is trim mode + +@status current Introduced in 2.3.10 +*/ +static int luaModelGetFlightMode(lua_State * L) +{ + unsigned int idx = luaL_checkunsigned(L, 1); + if (idx < MAX_FLIGHT_MODES) { + FlightModeData * fm = flightModeAddress(idx); + lua_newtable(L); + lua_pushtablezstring(L, "name", fm->name); + lua_pushtableinteger(L, "switch", fm->swtch); + lua_pushtableinteger(L, "fadeIn", fm->fadeIn); + lua_pushtableinteger(L, "fadeOut", fm->fadeOut); + lua_pushstring(L, "trimsValues"); + lua_newtable(L); + for (uint8_t i = 0; i < NUM_TRIMS; i++) { + lua_pushinteger(L, i); + lua_pushinteger(L, fm->trim[i].value); + lua_settable(L, -3); + } + lua_settable(L, -3); + lua_pushstring(L, "trimsModes"); + lua_newtable(L); + for (uint8_t i = 0; i < NUM_TRIMS; i++) { + lua_pushinteger(L, i); + lua_pushinteger(L, fm->trim[i].mode); + lua_settable(L, -3); + } + lua_settable(L, -3); + } + else { + lua_pushnil(L); + } + return 1; +} + +/*luadoc +@function model.setFlightMode(index, params) + +Set Flight mode parameters + +@param index (unsigned number) flight mode number (use 0 for FM0) + +@param params see model.getFlightMode return format for table format. + +@status current Introduced in 2.3.10 +*/ +static int luaModelSetFlightMode(lua_State * L) +{ + unsigned int flightMode = luaL_checkunsigned(L, 1); + + if (flightMode >= MAX_FLIGHT_MODES) { + lua_pushinteger(L, 2); + return 1; + } + FlightModeData * fm = flightModeAddress(flightMode); + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TSTRING); // key is string + const char * key = luaL_checkstring(L, -2); + if (!strcmp(key, "name")) { + const char * name = luaL_checkstring(L, -1); + str2zchar(fm->name, name, sizeof(fm->name)); + } + else if (!strcmp(key, "switch")) { + fm->swtch = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "fadeIn")) { + fm->fadeIn = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "fadeOut")) { + fm->fadeOut = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "trimsValues")) { + luaL_checktype(L, -1, LUA_TTABLE); + uint8_t idx = 0; + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1), idx++) { + int16_t val = luaL_checkinteger(L, -1); + if (idx < NUM_TRIMS) + fm->trim[idx].value = (val & 0x3FF); + } + } + else if (!strcmp(key, "trimsModes")) { + luaL_checktype(L, -1, LUA_TTABLE); + uint8_t idx = 0; + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1), idx++) { + uint16_t val = luaL_checkinteger(L, -1); + if (idx < NUM_TRIMS) + fm->trim[idx].mode = (val & 0x1F); + } + } + } + storageDirty(EE_MODEL); + lua_pushinteger(L, 0); + return 1; +} + /*luadoc @function model.getInput(input, line) @@ -376,6 +506,7 @@ Return input data for given input and line number @retval table input data: * `name` (string) input line name + * `inputName` (string) input input name * `source` (number) input source index * `weight` (number) input weight * `offset` (number) input offset @@ -383,8 +514,9 @@ Return input data for given input and line number * `curveType` (number) curve type (function, expo, custom curve) * `curveValue` (number) curve index * `carryTrim` (boolean) input trims applied + * 'flightModes' (table) table of enabled flightModes {0,2,7} means that the input is enabled for FM0, FM2 and FM7 -@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3 +@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, flightModes, inputName added 2.3.10 */ static int luaModelGetInput(lua_State *L) { @@ -396,6 +528,7 @@ static int luaModelGetInput(lua_State *L) ExpoData * expo = expoAddress(first+idx); lua_newtable(L); lua_pushtablezstring(L, "name", expo->name); + lua_pushtablezstring(L, "inputName", g_model.inputNames[chn]); lua_pushtableinteger(L, "source", expo->srcRaw); lua_pushtableinteger(L, "weight", expo->weight); lua_pushtableinteger(L, "offset", expo->offset); @@ -403,6 +536,16 @@ static int luaModelGetInput(lua_State *L) lua_pushtableinteger(L, "curveType", expo->curve.type); lua_pushtableinteger(L, "curveValue", expo->curve.value); lua_pushtableinteger(L, "carryTrim", expo->carryTrim); + lua_pushstring(L, "flightModes"); + lua_newtable(L); + for (int i = 0, cnt = 0; i < MAX_FLIGHT_MODES; i++) { + if (!(expo->flightModes & (1 << i))) { + lua_pushinteger(L, cnt++); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + } + lua_settable(L, -3); } else { lua_pushnil(L); @@ -421,7 +564,7 @@ Insert an Input at specified line @param value (table) input data, see model.getInput() -@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3 +@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, inputName added 2.3.10 */ static int luaModelInsertInput(lua_State *L) { @@ -444,6 +587,10 @@ static int luaModelInsertInput(lua_State *L) const char * name = luaL_checkstring(L, -1); str2zchar(expo->name, name, sizeof(expo->name)); } + else if (!strcmp(key, "inputName")) { + const char * name = luaL_checkstring(L, -1); + str2zchar(g_model.inputNames[chn], name, LEN_INPUT_NAME); + } else if (!strcmp(key, "source")) { expo->srcRaw = luaL_checkinteger(L, -1); } @@ -465,6 +612,16 @@ static int luaModelInsertInput(lua_State *L) else if (!strcmp(key, "carryTrim")) { expo->carryTrim = lua_toboolean(L, -1); } + else if (!strcmp(key, "flightModes")) { + luaL_checktype(L, -1, LUA_TTABLE); + int flighModes = 0x1FF; + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + uint16_t val = luaL_checkinteger(L, -1); + if (val < MAX_FLIGHT_MODES) + flighModes &= ~(1 << val); + } + expo->flightModes = flighModes; + } } } @@ -596,8 +753,9 @@ Get configuration for specified Mix * `delayDown` (number) delay down * `speedUp` (number) speed up * `speedDown` (number) speed down + * 'flightModes' (table) table of enabled flightModes {0,2,7} means that the input is enabled for FM0, FM2 and FM7 -@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13 +@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13, flightModes added 2.3.10 */ static int luaModelGetMix(lua_State *L) { @@ -623,6 +781,16 @@ static int luaModelGetMix(lua_State *L) lua_pushtableinteger(L, "delayDown", mix->delayDown); lua_pushtableinteger(L, "speedUp", mix->speedUp); lua_pushtableinteger(L, "speedDown", mix->speedDown); + lua_pushstring(L, "flightModes"); + lua_newtable(L); + for (int i = 0, cnt = 0; i < MAX_FLIGHT_MODES; i++) { + if (!(mix->flightModes & (1 << i))) { + lua_pushinteger(L, cnt++); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + } + lua_settable(L, -3); } else { lua_pushnil(L); @@ -641,7 +809,7 @@ Insert a mixer line into Channel @param value (table) see model.getMix() for table format -@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13 +@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13, flightModes added 2.3.10 */ static int luaModelInsertMix(lua_State *L) { @@ -706,6 +874,16 @@ static int luaModelInsertMix(lua_State *L) else if (!strcmp(key, "speedDown")) { mix->speedDown = luaL_checkinteger(L, -1); } + else if (!strcmp(key, "flightModes")) { + luaL_checktype(L, -1, LUA_TTABLE); + int flighModes = 0x1FF; + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + uint16_t val = luaL_checkinteger(L, -1); + if (val < MAX_FLIGHT_MODES) + flighModes &= ~(1 << val); + } + mix->flightModes = flighModes; + } } } @@ -997,7 +1175,7 @@ static int luaModelSetCurve(lua_State *L) bool isX = !strcmp(key, "x"); for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - int idx = luaL_checkinteger(L, -2)-1; + int idx = luaL_checkinteger(L, -2) - 1; if (idx < 0 || idx > MAX_POINTS_PER_CURVE) { lua_pushinteger(L, 4); return 1; @@ -1418,6 +1596,9 @@ const luaL_Reg modelLib[] = { { "getTimer", luaModelGetTimer }, { "setTimer", luaModelSetTimer }, { "resetTimer", luaModelResetTimer }, + { "deleteFlightModes", luaModelDeleteFlightModes }, + { "getFlightMode", luaModelGetFlightMode }, + { "setFlightMode", luaModelSetFlightMode }, { "getInputsCount", luaModelGetInputsCount }, { "getInput", luaModelGetInput }, { "insertInput", luaModelInsertInput }, diff --git a/radio/src/lua/widgets.cpp b/radio/src/lua/widgets.cpp index 271a6ffaf..75260b068 100644 --- a/radio/src/lua/widgets.cpp +++ b/radio/src/lua/widgets.cpp @@ -253,23 +253,23 @@ class LuaWidget: public Widget LuaWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData, int widgetData): Widget(factory, zone, persistentData), widgetData(widgetData), - errorMessage(0) + errorMessage(nullptr) { } - virtual ~LuaWidget() + ~LuaWidget() override { luaL_unref(lsWidgets, LUA_REGISTRYINDEX, widgetData); - if (errorMessage) free(errorMessage); + free(errorMessage); } - virtual void update(); + void update() override; void refresh() override; - virtual void background(); + void background() override; - virtual const char * getErrorMessage() const; + const char * getErrorMessage() const override; protected: int widgetData; @@ -300,7 +300,7 @@ class LuaWidgetFactory: public WidgetFactory { } - virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const + Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const override { if (lsWidgets == 0) return 0; if (init) { diff --git a/radio/src/main.cpp b/radio/src/main.cpp index d17c4d0a7..4f634c340 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -26,6 +26,8 @@ uint8_t currentSpeakerVolume = 255; uint8_t requiredSpeakerVolume = 255; +uint8_t currentBacklightBright = 255; +uint8_t requiredBacklightBright = 255; uint8_t mainRequestFlags = 0; #if defined(LIBOPENUI) diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 61be1aeef..8b67e9dc8 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -524,13 +524,13 @@ int getStickTrimValue(int stick, int stickValue) return 0; int trim = trims[stick]; - if (stick == THR_STICK) { - if (g_model.thrTrim) { - int trimMin = g_model.extendedTrims ? 2*TRIM_EXTENDED_MIN : 2*TRIM_MIN; - trim = ((g_model.throttleReversed ? (trim+trimMin) : (trim-trimMin)) * (RESX-stickValue)) >> (RESX_SHIFT+1); - } - if (g_model.throttleReversed) { + uint8_t thrTrimSw = g_model.getThrottleStickTrimSource() - MIXSRC_FIRST_TRIM; + if (stick == thrTrimSw) { + if (g_model.throttleReversed) trim = -trim; + if (g_model.thrTrim) { + trim = (g_model.extendedTrims) ? 2*TRIM_EXTENDED_MAX + trim : 2*TRIM_MAX + trim; + trim = trim * (1024 - stickValue) / (2*RESX); } } return trim; @@ -956,6 +956,7 @@ void evalMixes(uint8_t tick10ms) // must be done before limits because of the applyLimit function: it checks for safety switches which would be not initialized otherwise if (tick10ms) { requiredSpeakerVolume = g_eeGeneral.speakerVolume + VOLUME_LEVEL_DEF; + requiredBacklightBright = g_eeGeneral.backlightBright; if (!g_model.noGlobalFunctions) { evalFunctions(g_eeGeneral.customFn, globalFunctionsContext); diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 7fe8492f1..6733fc17f 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -38,7 +38,8 @@ #else #define IS_TRAINER_EXTERNAL_MODULE() false #endif -#define IS_TRAINER_AUX_SERIAL() (g_eeGeneral.auxSerialMode==UART_MODE_SBUS_TRAINER) + +#define IS_TRAINER_AUX_SERIAL() (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) #define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE) @@ -54,7 +55,7 @@ #define IS_HAPTIC_FUNC(func) (0) #endif -#define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE) +#define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE || (func == FUNC_BACKLIGHT)) #define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func)) #define CFN_EMPTY(p) (!(p)->swtch) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 603a5cd27..1928eee0f 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -27,6 +27,10 @@ #include "view_main.h" #endif +#if defined(PCBSKY9X) +#include "audio_driver.h" +#endif + RadioData g_eeGeneral; ModelData g_model; @@ -276,7 +280,9 @@ void generalDefault() #if defined(PCBHORUS) g_eeGeneral.blOffBright = 20; -#else +#endif + +#if defined(LCD_CONTRAST_DEFAULT) g_eeGeneral.contrast = LCD_CONTRAST_DEFAULT; #endif @@ -694,12 +700,19 @@ void checkBacklight() } } - bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || (g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter) || isFunctionActive(FUNCTION_BACKLIGHT)); - if (flashCounter) backlightOn = !backlightOn; - if (backlightOn) + bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || (g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter)); + + if (flashCounter) { + backlightOn = !backlightOn; + } + + if (backlightOn) { + currentBacklightBright = requiredBacklightBright; BACKLIGHT_ENABLE(); - else + } + else { BACKLIGHT_DISABLE(); + } } } @@ -1690,28 +1703,40 @@ void opentxResume() void instantTrim() { - int16_t anas_0[MAX_INPUTS]; + int16_t anas_0[MAX_INPUTS]; evalInputs(e_perout_mode_notrainer | e_perout_mode_nosticks); memcpy(anas_0, anas, sizeof(anas_0)); evalInputs(e_perout_mode_notrainer); - for (uint8_t stick=0; sticksrcRaw-MIXSRC_Rud == stick) { - delta = anas[ed->chn] - anas_0[ed->chn]; - break; + uint8_t trimFlightMode = getTrimFlightMode(mixerCurrentFlightMode, stick); + for (uint8_t i = 0; i < MAX_EXPOS; i++) { + ExpoData * expo = expoAddress(i); + if (!EXPO_VALID(expo)) + break; // end of list + if (stick == expo->srcRaw - MIXSRC_FIRST_STICK) { + if (expo->carryTrim < 0) { + // only default trims will be taken into account + addTrim = false; + break; + } + auto newDelta = anas[expo->chn] - anas_0[expo->chn]; + if (addTrim && delta != newDelta) { + // avoid 2 different delta values + addTrim = false; + break; + } + addTrim = true; + delta = newDelta; } } - if (abs(delta) >= INSTANT_TRIM_MARGIN) { + if (addTrim && abs(delta) >= INSTANT_TRIM_MARGIN) { int16_t trim = limit(TRIM_EXTENDED_MIN, (delta + trims[stick]) / 2, TRIM_EXTENDED_MAX); - setTrimValue(trim_phase, stick, trim); + setTrimValue(trimFlightMode, stick, trim); } } } @@ -2005,6 +2030,7 @@ void opentxInit() #endif currentSpeakerVolume = requiredSpeakerVolume = g_eeGeneral.speakerVolume + VOLUME_LEVEL_DEF; + currentBacklightBright = requiredBacklightBright = g_eeGeneral.backlightBright; #if !defined(SOFTWARE_VOLUME) setScaledVolume(currentSpeakerVolume); #endif @@ -2086,7 +2112,7 @@ int main() // important to disable it before commencing with system initialisation (or // we could put a bunch more WDG_RESET()s in. But I don't like that approach // during boot up.) -#if defined(PCBTARANIS) +#if defined(LCD_CONTRAST_DEFAULT) g_eeGeneral.contrast = LCD_CONTRAST_DEFAULT; #endif @@ -2127,6 +2153,10 @@ int main() inline uint32_t PWR_PRESS_SHUTDOWN_DELAY() { + // Instant off when both power button are pressed + if (pwrForcePressed()) + return 0; + return (2 - g_eeGeneral.pwrOffSpeed) * 100; } diff --git a/radio/src/opentx.h b/radio/src/opentx.h index b6d870889..cf77902ab 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -501,6 +501,7 @@ void doMixerCalculations(); void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms); void checkTrims(); +extern uint8_t currentBacklightBright; void perMain(); void per10ms(); @@ -550,7 +551,7 @@ bool setTrimValue(uint8_t phase, uint8_t idx, int trim); #if defined(PCBSKY9X) #define ROTARY_ENCODER_GRANULARITY (2 << g_eeGeneral.rotarySteps) -#elif defined(RADIO_FAMILY_T16) +#elif defined(RADIO_FAMILY_T16) && !defined(RADIO_T18) #define ROTARY_ENCODER_GRANULARITY (1) #else #define ROTARY_ENCODER_GRANULARITY (2) @@ -685,6 +686,7 @@ inline int calcRESXto100(int x) } #if defined(COLORLCD) +extern const char fw_stamp[]; extern const char vers_stamp[]; extern const char date_stamp[]; extern const char time_stamp[]; @@ -821,7 +823,6 @@ enum FunctionsActive { FUNCTION_TRAINER_CHANNELS = FUNCTION_TRAINER_STICK1 + NUM_STICKS, FUNCTION_INSTANT_TRIM, FUNCTION_VARIO, - FUNCTION_BACKLIGHT, #if defined(SDCARD) FUNCTION_LOGS, #endif diff --git a/radio/src/options.h b/radio/src/options.h index e8bf634c1..f2b3c8369 100644 --- a/radio/src/options.h +++ b/radio/src/options.h @@ -22,25 +22,31 @@ #ifndef OPENTX_OPTIONS_H #define OPENTX_OPTIONS_H -static const char * options[] = { +static const char * const options[] = { #if defined(AUTOUPDATE) "autoupdate", #endif #if defined(CROSSFIRE) "crossfire", #endif +#if defined(GHOST) + "ghost", +#endif #if !defined(MODULE_PROTOCOL_D8) "eu", #endif #if defined(FAI) - "faimode", + "FAImode", #endif #if defined(FAI_CHOICE) - "faichoice", + "FAIchoice", #endif #if defined(MODULE_PROTOCOL_FLEX) "flexr9m", #endif +#if defined(AFHDS3) + "afhds3", +#endif #if !defined(GVARS) "nogvars", #endif diff --git a/radio/src/pulses/afhds2.h b/radio/src/pulses/afhds2.h index baa1caa06..e6bab681b 100644 --- a/radio/src/pulses/afhds2.h +++ b/radio/src/pulses/afhds2.h @@ -21,6 +21,8 @@ #ifndef PULSES_AFHDS2_H_ #define PULSES_AFHDS2_H_ + +#include #include #include #include diff --git a/radio/src/pulses/afhds3.cpp b/radio/src/pulses/afhds3.cpp index c37dd4aa2..bafe7817c 100644 --- a/radio/src/pulses/afhds3.cpp +++ b/radio/src/pulses/afhds3.cpp @@ -18,85 +18,343 @@ * GNU General Public License for more details. */ - #include "afhds3.h" #include "../debug.h" #include "../definitions.h" +#include #define FAILSAFE_HOLD 1 #define FAILSAFE_CUSTOM 2 -namespace afhds3 { +#define MAX_RETRIES_AFHDS3 5 +extern void processFlySkySensor(const uint8_t * packet, uint8_t type); -uint8_t ModuleModeToState [] = { - ModuleState::STATE_READY, //not defined - ModuleState::STATE_STANDBY, //MODULE_MODE_E::STANDBY - ModuleState::STATE_BINDING, //MODULE_MODE_E::BIND - ModuleState::STATE_UPDATING_RX, //MODULE_MODE_E::RX_UPDATE - ModuleState::STATE_SYNC_DONE, //MODULE_MODE_E::RUN +extern void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inverted); + +namespace afhds3 +{ + +static const char* const moduleStateText[] = +{ + "Not ready", + "HW Error", + "Binding", + "Connecting", + "Connected", + "Standby", + "Waiting for update", + "Updating", + "Updating RX", + "Updating RX failed", + "Testing", + "Ready", + "HW test" }; -static const char* const moduleStateText[] = { - "", - "HW Error", - "Binding", - "Connecting", - "Connected", - "Standby", - "Waiting for update", - "Updating", - "Updating RX", - "Updating RX failed", - "Testing" - "Not ready", - "Ready", - "HW test" +static const char* const powerSourceText[] = +{ + "Unknown", + "Internal", + "External" }; -const char* afhds3::getState() { - if(data->state <= ModuleState::STATE_READY) return moduleStateText[data->state]; - return "Unknown"; +static const COMMAND periodicRequestCommands[] = +{ + COMMAND::MODULE_STATE, + COMMAND::MODULE_POWER_STATUS, + COMMAND::MODULE_GET_CONFIG, + COMMAND::VIRTUAL_FAILSAFE +}; + +//Address used in transmitted frames - it constrains of target address and source address +const uint8_t FrameAddress = DeviceAddress::TRANSMITTER | (DeviceAddress::MODULE << 4); + +//Static collection of afhds3 object instances by module +PulsesData* AFHDS3PulsesData[EXTERNAL_MODULE + 1] = { nullptr, nullptr }; + +//friends function that can access telemetry parsing method +void processTelemetryData(uint8_t module, uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize) +{ + if (AFHDS3PulsesData[module]) { + AFHDS3PulsesData[module]->processTelemetryData(data, rxBuffer, rxBufferCount, maxSize); + } } -void afhds3::putByte(uint8_t byte) { - this->putBytes(&byte, 1); +void CommandFifo::clearCommandFifo() +{ + memclear(commandFifo, sizeof(commandFifo)); + setIndex = getIndex = 0; } -void afhds3::putBytes(uint8_t* data, int length) { +void CommandFifo::enqueueACK(COMMAND command, uint8_t frameNumber) +{ + uint32_t next = nextIndex(setIndex); + if (next != getIndex) { + commandFifo[setIndex].command = command; + commandFifo[setIndex].frameType = FRAME_TYPE::RESPONSE_ACK; + commandFifo[setIndex].payload = 0; + commandFifo[setIndex].payloadSize = 0; + commandFifo[setIndex].frameNumber = frameNumber; + commandFifo[setIndex].useFrameNumber = true; + setIndex = next; + } +} + +void CommandFifo::enqueue(COMMAND command, FRAME_TYPE frameType, bool useData, uint8_t byteContent) +{ + uint32_t next = nextIndex(setIndex); + if (next != getIndex) { + commandFifo[setIndex].command = command; + commandFifo[setIndex].frameType = frameType; + commandFifo[setIndex].payload = byteContent; + commandFifo[setIndex].payloadSize = useData ? 1 : 0; + commandFifo[setIndex].frameNumber = 0; + commandFifo[setIndex].useFrameNumber = false; + setIndex = next; + } +} + +void PulsesData::getStatusString(char * buffer) const +{ + strcpy(buffer, this->state <= ModuleState::STATE_READY ? moduleStateText[this->state] : "Unknown"); +} + +void PulsesData::getPowerStatus(char* buffer) const +{ + strcpy(buffer, this->powerSource <= MODULE_POWER_SOURCE::EXTERNAL ? powerSourceText[this->powerSource] : "Unknown"); +} + +void PulsesData::processTelemetryData(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize) +{ + if (rxBufferCount == 0 && byte != AfhdsSpecialChars::START) { + TRACE("AFHDS3 [SKIP] %02X", byte); + this->esc_state = 0; + return; + } + + if (byte == AfhdsSpecialChars::ESC) { + this->esc_state = rxBufferCount; + return; + } + + if (rxBufferCount > 1 && byte == AfhdsSpecialChars::END) { + rxBuffer[rxBufferCount++] = byte; + parseData(rxBuffer, rxBufferCount); + rxBufferCount = 0; + return; + } + + if (this->esc_state && byte == AfhdsSpecialChars::ESC_END) { + byte = AfhdsSpecialChars::END; + } + else if (esc_state && byte == AfhdsSpecialChars::ESC_ESC) { + byte = AfhdsSpecialChars::ESC; + } + //reset esc index + this->esc_state = 0; + + if (rxBufferCount >= maxSize) { + TRACE("AFHDS3 [BUFFER OVERFLOW]"); + rxBufferCount = 0; + } + rxBuffer[rxBufferCount++] = byte; +} + +bool PulsesData::isConnectedUnicast() +{ + return cfg.config.telemetry == TELEMETRY::TELEMETRY_ENABLED && this->state == ModuleState::STATE_SYNC_DONE; +} + +bool PulsesData::isConnectedMulticast() +{ + return cfg.config.telemetry == TELEMETRY::TELEMETRY_DISABLED && this->state == ModuleState::STATE_SYNC_RUNNING; +} + +void PulsesData::setupFrame() +{ + if (operationState == State::AWAITING_RESPONSE) { + if (repeatCount++ < MAX_RETRIES_AFHDS3) { + return; //re-send + } + else + { + TRACE("AFHDS3 [NO RESP] module state %d", this->state); + clearFrameData(); + this->state = ModuleState::STATE_NOT_READY; + } + } + else if (operationState == State::UNKNOWN) { + this->state = ModuleState::STATE_NOT_READY; + } + repeatCount = 0; + if (this->state == ModuleState::STATE_NOT_READY) { + TRACE("AFHDS3 [GET MODULE READY]"); + putFrame(COMMAND::MODULE_READY, FRAME_TYPE::REQUEST_GET_DATA); + return; + } + + //check waiting commands + if (!isEmpty()) { + Frame f = commandFifo[getIndex]; + putFrame(f.command, f.frameType, &f.payload, f.payloadSize, f.useFrameNumber ? &f.frameNumber : &frame_index); + getIndex = nextIndex(getIndex); + TRACE("AFHDS3 [CMD QUEUE] cmd: %d frameType %d, useFrameNumber %d frame Number %d size %d", f.command, f.frameType, f.useFrameNumber, f.frameNumber, f.payloadSize); + return; + } + + //config should be loaded already + if (syncSettings()) { + return; + } + + //if module is ready but not started + if (this->state == ModuleState::STATE_READY || this->state == ModuleState::STATE_STANDBY) { + cmdCount = 0; + repeatCount = 0; + requestInfoAndRun(true); + return; + } + + ::ModuleSettingsMode moduleMode = getModuleMode(module_index); + + if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_BIND) { + if (state != STATE_BINDING) { + TRACE("AFHDS3 [BIND]"); + setConfigFromModel(); + putFrame(COMMAND::MODULE_SET_CONFIG, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, cfg.buffer, sizeof(cfg.buffer)); + requestedModuleMode = MODULE_MODE_E::BIND; + enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, requestedModuleMode); + return; + } + } + else if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_RANGECHECK) { + if (cfg.config.runPower != RUN_POWER::RUN_POWER_FIRST) { + TRACE("AFHDS3 [RANGE CHECK]"); + cfg.config.runPower = RUN_POWER::RUN_POWER_FIRST; + uint8_t data[] = { 0x13, 0x20, 0x02, cfg.config.runPower, 0 }; + TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower); + putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data)); + return; + } + } + else if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_NORMAL) { //exit bind + if (state == STATE_BINDING) { + TRACE("AFHDS3 [EXIT BIND]"); + requestedModuleMode = MODULE_MODE_E::RUN; + putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &requestedModuleMode, 1); + return; + } + } + + bool isConnected = isConnectedUnicast() || isConnectedMulticast(); + + if (cmdCount++ >= 150) { + cmdCount = 0; + if (cmdIndex >= sizeof(periodicRequestCommands)) { + cmdIndex = 0; + } + COMMAND cmd = periodicRequestCommands[cmdIndex++]; + + if (cmd == COMMAND::VIRTUAL_FAILSAFE) { + if (isConnected) { + if (isConnectedMulticast()) { + TRACE("AFHDS ONE WAY FAILSAFE"); + uint16_t failSafe[MAX_CHANNELS + 1] = { ((MAX_CHANNELS << 8) | CHANNELS_DATA_MODE::FAIL_SAFE), 0 }; + setFailSafe((int16_t*) (&failSafe[1])); + putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, (uint8_t*) failSafe, MAX_CHANNELS * 2 + 2); + } + else { + TRACE("AFHDS TWO WAYS FAILSAFE"); + uint8_t failSafe[3 + MAX_CHANNELS * 2] = { 0x11, 0x60, MAX_CHANNELS * 2 }; + setFailSafe((int16_t*) (failSafe + 3)); + putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, failSafe, 3 + MAX_CHANNELS * 2); + } + } + else { + putFrame(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + } + } + else + { + putFrame(cmd, FRAME_TYPE::REQUEST_GET_DATA); + } + } + else if (isConnected) { + sendChannelsData(); + } + else { + //default frame - request state + putFrame(MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + } +} + +void PulsesData::init(uint8_t moduleIndex, bool resetFrameCount) +{ + module_index = moduleIndex; + AFHDS3PulsesData[module_index] = this; + //clear local vars because it is member of union + moduleData = &g_model.moduleData[module_index]; + operationState = State::UNKNOWN; + state = ModuleState::STATE_NOT_READY; + clearFrameData(); +} + +void PulsesData::clearFrameData() +{ + TRACE("AFHDS3 clearFrameData"); + reset(); + clearCommandFifo(); + repeatCount = 0; + cmdCount = 0; + cmdIndex = 0; + this->frame_index = 1; + this->timeout = 0; + this->esc_state = 0; +} + +void PulsesData::putBytes(uint8_t* data, int length) +{ for (int i = 0; i < length; i++) { uint8_t byte = data[i]; - this->data->crc += byte; + this->crc += byte; if (END == byte) { - *this->data->ptr++ = ESC; - *this->data->ptr++ = ESC_END; + sendByte(ESC); + sendByte(ESC_END); } else if (ESC == byte) { - *this->data->ptr++ = ESC; - *this->data->ptr++ = ESC_ESC; + sendByte(ESC); + sendByte(ESC_ESC); } else { - *this->data->ptr++ = byte; + sendByte(byte); } } } -void afhds3::putHeader(COMMAND command, FRAME_TYPE frame) { +void PulsesData::putFrame(COMMAND command, FRAME_TYPE frame, uint8_t* data, uint8_t dataLength, uint8_t* frameIndex) +{ + //header operationState = State::SENDING_COMMAND; - data->ptr = this->data->pulses; - data->crc = 0; - *data->ptr++ = END; - uint8_t buffer[] = { FrameAddress, data->frame_index, frame, command}; + reset(); + this->crc = 0; + sendByte(START); + if (frameIndex == nullptr) { + frameIndex = &this->frame_index; + } + uint8_t buffer[] = {FrameAddress, *frameIndex, frame, command}; putBytes(buffer, 4); -} + //payload + if (dataLength > 0) { + putBytes(data, dataLength); + } + //footer + uint8_t crcValue = this->crc ^ 0xff; + putBytes(&crcValue, 1); + sendByte(END); + *frameIndex = *frameIndex + 1; -void afhds3::putFooter() { - putByte(data->crc ^ 0xff); - *data->ptr++ = END; - data->frame_index++; - - switch((FRAME_TYPE)data->pulses[3]) - { + switch (frame) { case FRAME_TYPE::REQUEST_GET_DATA: case FRAME_TYPE::REQUEST_SET_EXPECT_ACK: case FRAME_TYPE::REQUEST_SET_EXPECT_DATA: @@ -105,25 +363,8 @@ void afhds3::putFooter() { default: operationState = State::IDLE; } -} -void afhds3::putFrame(COMMAND command, FRAME_TYPE frame, uint8_t* data, uint8_t dataLength){ - putHeader(command, frame); - if(dataLength > 0) putBytes(data, dataLength); - putFooter(); -} - -void afhds3::addToQueue(COMMAND command, FRAME_TYPE frameType, uint8_t* data, uint8_t dataLength) { - request* r = new request(command, frameType, data, dataLength); - commandQueue.push(r); -} - -void afhds3::clearQueue() { - while(!commandQueue.empty()) { - request* r = commandQueue.front(); - delete r; - commandQueue.pop(); - } + flush(); } bool checkCRC(const uint8_t* data, uint8_t size) @@ -136,58 +377,73 @@ bool checkCRC(const uint8_t* data, uint8_t size) return (crc ^ 0xff) == data[size]; } -bool containsData(enum FRAME_TYPE frameType) { - return frameType == FRAME_TYPE::RESPONSE_DATA || frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA || - frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK || frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA || - frameType == FRAME_TYPE::REQUEST_SET_NO_RESP; +bool containsData(enum FRAME_TYPE frameType) +{ + return (frameType == FRAME_TYPE::RESPONSE_DATA || + frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA || + frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK || + frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA || + frameType == FRAME_TYPE::REQUEST_SET_NO_RESP); } -void afhds3::setState(uint8_t state) { - if(state == data->state) return; - uint8_t oldState = data->state; - data->state = state; - if(oldState == ModuleState::STATE_BINDING) { - if(operationCallback != nullptr) { - operationCallback(false); - operationCallback = nullptr; - } +void PulsesData::setState(uint8_t state) +{ + if (state == this->state) { + return; + } + uint8_t oldState = this->state; + this->state = state; + if (oldState == ModuleState::STATE_BINDING) { + setModuleMode(module_index, ::ModuleSettingsMode::MODULE_MODE_NORMAL); + } + if (state == ModuleState::STATE_NOT_READY) { + operationState = State::UNKNOWN; } } -void afhds3::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) { +void PulsesData::requestInfoAndRun(bool send) +{ + if (!send) { + enqueue(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); + } + enqueue(COMMAND::MODULE_POWER_STATUS, FRAME_TYPE::REQUEST_GET_DATA); + requestedModuleMode = MODULE_MODE_E::RUN; + enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, (uint8_t) MODULE_MODE_E::RUN); + if (send) { + putFrame(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); + } +} - if(!checkCRC(rxBuffer, rxBufferCount - 2)) { +void PulsesData::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) +{ + + if (!checkCRC(rxBuffer, rxBufferCount - 2)) { TRACE("AFHDS3 [INVALID CRC]"); return; } AfhdsFrame* responseFrame = reinterpret_cast(rxBuffer); - AfhdsFrame* requestFrame = reinterpret_cast(data->pulses); - uint8_t oldState = data->state; - if(containsData((enum FRAME_TYPE)responseFrame->frameType)) { - switch(responseFrame->command) - { + if (containsData((enum FRAME_TYPE) responseFrame->frameType)) { + switch (responseFrame->command) { case COMMAND::MODULE_READY: TRACE("AFHDS3 [MODULE_READY] %02X", responseFrame->value); - setState(responseFrame->value == MODULE_STATUS_READY ? ModuleState::STATE_READY : ModuleState::STATE_NOT_READY); - if(data->state == ModuleState::STATE_READY && oldState != data->state) { - addToQueue(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); - addToQueue(COMMAND::MODULE_POWER_STATUS, FRAME_TYPE::REQUEST_GET_DATA); - addToQueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA); - uint8_t mode = MODULE_MODE_E::RUN; - addToQueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &mode, 1); - //addToQueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + if (responseFrame->value == MODULE_STATUS_READY) { + setState(ModuleState::STATE_READY); + requestInfoAndRun(); + } + else { + setState(ModuleState::STATE_NOT_READY); } break; case COMMAND::MODULE_GET_CONFIG: - std::memcpy((void*)cfg.buffer, &responseFrame->value, sizeof(cfg.buffer)); - TRACE("AFHDS3 [MODULE_GET_CONFIG] telemetry %d", cfg.config.telemetry); - break; + std::memcpy((void*) cfg.buffer, &responseFrame->value, sizeof(cfg.buffer)); + TRACE("AFHDS3 [MODULE_GET_CONFIG] bind power %d run power %d mode %d pwm/ppm %d ibus/sbus %d", cfg.config.bindPower, cfg.config.runPower, cfg.config.telemetry, cfg.config.pulseMode, cfg.config.serialMode); + break; case COMMAND::MODULE_VERSION: - std::memcpy((void*)&version, &responseFrame->value, sizeof(version)); + std::memcpy((void*) &version, &responseFrame->value, sizeof(version)); TRACE("AFHDS3 [MODULE_VERSION] Product %d, HW %d, BOOT %d, FW %d", version.productNumber, version.hardwereVersion, version.bootloaderVersion, version.firmwareVersion); break; case COMMAND::MODULE_POWER_STATUS: - powerSource = (enum MODULE_POWER_SOURCE)responseFrame->value; + powerSource = (enum MODULE_POWER_SOURCE) responseFrame->value; TRACE("AFHDS3 [MODULE_POWER_STATUS], %d", powerSource); break; case COMMAND::MODULE_STATE: @@ -195,249 +451,225 @@ void afhds3::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) { setState(responseFrame->value); break; case COMMAND::MODULE_MODE: - TRACE("AFHDS3 [MODULE_MODE] %02X", responseFrame->value); - if(responseFrame->value != CMD_RESULT::SUCCESS) { - setState(ModuleState::STATE_NOT_READY); + TRACE("AFHDS3 [MODULE_MODE] %02X", responseFrame->value); + if (responseFrame->value != CMD_RESULT::SUCCESS) { + setState(ModuleState::STATE_NOT_READY); + } + else { + if (requestedModuleMode == MODULE_MODE_E::RUN) { + enqueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA); + enqueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + } + requestedModuleMode = MODULE_MODE_UNKNOWN; } - else addToQueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); - break; case COMMAND::MODULE_SET_CONFIG: - if(responseFrame->value != CMD_RESULT::SUCCESS) { + if (responseFrame->value != CMD_RESULT::SUCCESS) { setState(ModuleState::STATE_NOT_READY); } TRACE("AFHDS3 [MODULE_SET_CONFIG], %02X", responseFrame->value); break; case COMMAND::TELEMETRY_DATA: + { uint8_t* telemetry = &responseFrame->value; - uint8_t length = telemetry[1]; - uint8_t id = telemetry[2]; - if(telemetry[0] == 0x22) { - if(length == 5) { - if(id == 0xFA) telemetry[2] = 0xF8; //remap to afhds3 snr - processSensor(telemetry + 2, 0xAA); + + if (telemetry[0] == 0x22) { + telemetry++; + while (telemetry < rxBuffer + rxBufferCount) { + uint8_t length = telemetry[0]; + uint8_t id = telemetry[1]; + if (id == 0xFE) { + id = 0xF7; //use new id because format is different + } + if (length == 0 || telemetry + length > rxBuffer + rxBufferCount) { + break; + } + if (length == 4) { + //one byte value fill missing byte + uint8_t data[] = { id, telemetry[2], telemetry[3], 0 }; + ::processFlySkySensor(data, 0xAA); + } + if (length == 5) { + if (id == 0xFA) { + telemetry[1] = 0xF8; //remap to afhds3 snr + } + ::processFlySkySensor(telemetry + 1, 0xAA); + } + else if (length == 6 && id == FRM302_STATUS) { + //convert to ibus + uint16_t t = (uint16_t) (((int16_t) telemetry[3] * 10) + 400); + uint8_t dataTemp[] = { ++id, telemetry[2], (uint8_t) (t & 0xFF), (uint8_t) (t >> 8) }; + ::processFlySkySensor(dataTemp, 0xAA); + uint8_t dataVoltage[] = { ++id, telemetry[2], telemetry[4], telemetry[5] }; + ::processFlySkySensor(dataVoltage, 0xAA); + } + else if (length == 7) { + ::processFlySkySensor(telemetry + 1, 0xAC); + } + telemetry += length; } - else if(length == 6 && id == FRM302_STATUS) { - //convert to ibus - uint16_t t = (uint16_t)(((int16_t)telemetry[4] *10) + 400); - uint8_t dataTemp[] = { ++id, telemetry[3], (uint8_t)(t & 0xFF), (uint8_t)(t >> 8)}; - processSensor(dataTemp, 0xAA); - uint8_t dataVoltage[] = { ++id, telemetry[3], telemetry[5], telemetry[6] }; - processSensor(dataVoltage, 0xAA); - } - else if(length == 7) processSensor(telemetry + 2, 0xAC); + } + } + break; + case COMMAND::COMMAND_RESULT: + { + //AfhdsFrameData* respData = responseFrame->GetData(); + //TRACE("COMMAND RESULT %02X result %d datalen %d", respData->CommandResult.command, respData->CommandResult.result, respData->CommandResult.respLen); } break; } } - if(responseFrame->frameType == FRAME_TYPE::REQUEST_GET_DATA || responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA) - { + if (responseFrame->frameType == FRAME_TYPE::REQUEST_GET_DATA || responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA) { TRACE("Command %02X NOT IMPLEMENTED!", responseFrame->command); } else if (responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK) { - addToQueue((enum COMMAND)responseFrame->command, FRAME_TYPE::RESPONSE_ACK); + //check if such request is not queued + if (!isEmpty()) { + Frame f = commandFifo[getIndex]; + if (f.frameType == FRAME_TYPE::RESPONSE_ACK && f.frameNumber == responseFrame->frameNumber) { + TRACE("ACK for frame %02X already queued", responseFrame->frameNumber); + return; + } + } + TRACE("AFHDS3 [QUEUE ACK] cmd %02X type %02X number %02X", responseFrame->command, responseFrame->frameType, responseFrame->frameNumber); + enqueueACK((enum COMMAND) responseFrame->command, responseFrame->frameNumber); } - else if(responseFrame->frameType == FRAME_TYPE::RESPONSE_DATA || responseFrame->frameType == FRAME_TYPE::RESPONSE_ACK) { - if(operationState == State::AWAITING_RESPONSE /* && requestFrame->command == responseFrame->command*/) { + else if (responseFrame->frameType == FRAME_TYPE::RESPONSE_DATA || responseFrame->frameType == FRAME_TYPE::RESPONSE_ACK) { + if (operationState == State::AWAITING_RESPONSE) { operationState = State::IDLE; } } } -void afhds3::onDataReceived(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize) { - if (rxBufferCount == 0 && byte != AfhdsSpecialChars::START) { - TRACE("AFHDS3 [SKIP] %02X", byte); - data->esc_state = 0; - return; - } - - if (byte == AfhdsSpecialChars::ESC) { - data->esc_state = rxBufferCount; - return; - } - - if (rxBufferCount > 1 && byte == AfhdsSpecialChars::END) { - rxBuffer[rxBufferCount++] = byte; - parseData(rxBuffer, rxBufferCount); - rxBufferCount = 0; - return; - } - - if (data->esc_state && byte == AfhdsSpecialChars::ESC_END) byte = AfhdsSpecialChars::END; - else if (data->esc_state && byte == AfhdsSpecialChars::ESC_ESC) byte = AfhdsSpecialChars::ESC; - //reset esc index - data->esc_state = 0; - - if (rxBufferCount >= maxSize) { - TRACE("AFHDS3 [BUFFER OVERFLOW]"); - rxBufferCount = 0; - } - rxBuffer[rxBufferCount++] = byte; -} -void afhds3::trace(const char* message) { - char buffer[256]; - char *pos = buffer; - for (int i = 0; i < data->ptr - data->pulses; i++) { - pos += std::snprintf(pos, buffer + sizeof(buffer) - pos, "%02X ", data->pulses[i]); - } - (*pos) = 0; - TRACE("%s size = %d data %s", message, data->ptr - data->pulses, buffer); -} -void afhds3::setupPulses() { - //TRACE("%d state %d repeatCount %d", (int)operationState, this->data->state, repeatCount); - if(operationState == State::AWAITING_RESPONSE) { - if(repeatCount++ < 5) return; //re-send - else reset(false); - } - data->ptr = data->pulses; - repeatCount = 0; - if (operationState == State::UNKNOWN || data->state == ModuleState::STATE_NOT_READY) { - putFrame(COMMAND::MODULE_READY, FRAME_TYPE::REQUEST_GET_DATA); - return; - } - - - //check waiting commands - if(!commandQueue.empty()) { - request* r = commandQueue.front(); - commandQueue.pop(); - putFrame(r->command, r->frameType, r->payload, r->payloadSize); - trace("AFHDS3 [CMD QUEUE] data"); - delete r; - return; - } - - //config should be loaded already - if(syncSettings()) return; - - switch(data->state) { - case ModuleState::STATE_READY: - reset(); - break; - case ModuleState::STATE_HW_ERROR: - case ModuleState::STATE_BINDING: - case ModuleState::STATE_UPDATING_RX: - case ModuleState::STATE_UPDATING_WAIT: - case ModuleState::STATE_UPDATING_MOD: - case ModuleState::STATE_SYNC_RUNNING: - case ModuleState::STATE_HW_TEST: - if(idleCount++ % 100 == 0) putFrame(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); - break; - case ModuleState::STATE_SYNC_DONE: - if(cfg.config.telemetry && idleCount++ % 800 == 0) { - uint8_t failSafe[3+MAX_CHANNELS*2] = {0x60, 0x12}; - uint8_t channels = setFailSafe((int16_t*)(failSafe + 3)); - failSafe[2] = channels *2; - putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, failSafe, 3 + channels*2); - //trace("AFHDS3 [AFHDS3 SET FAILSAFE] data"); - } - else sendChannelsData(); - break; - } +inline bool isSbus(uint8_t mode) +{ + return (mode & 1); } -bool afhds3::syncSettings() { - if (moduleData->afhds3.runPower != cfg.config.runPower) { +inline bool isPWM(uint8_t mode) +{ + return mode < 2; +} + +RUN_POWER PulsesData::getMaxRunPower() const +{ + if (powerSource == MODULE_POWER_SOURCE::EXTERNAL) { + return RUN_POWER::PLUS_33dBm; + } + + return RUN_POWER::PLUS_27dbm; +} + +RUN_POWER PulsesData::actualRunPower() const +{ + uint8_t actualRfPower = cfg.config.runPower; + if (getMaxRunPower() < actualRfPower) { + actualRfPower = getMaxRunPower(); + } + return (RUN_POWER) actualRfPower; +} + +RUN_POWER PulsesData::getRunPower() const +{ + RUN_POWER targetPower = (RUN_POWER) moduleData->afhds3.runPower; + if (getMaxRunPower() < targetPower) { + targetPower = getMaxRunPower(); + } + return targetPower; +} + +bool PulsesData::syncSettings() +{ + RUN_POWER targetPower = getRunPower(); + + /*not sure if we need to prevent them in bind mode*/ + if (getModuleMode(module_index) != ::ModuleSettingsMode::MODULE_MODE_BIND && targetPower != cfg.config.runPower) { cfg.config.runPower = moduleData->afhds3.runPower; - uint8_t data[] = { 0x20, 0x13, 0x01, moduleData->afhds3.runPower }; + uint8_t data[] = { 0x13, 0x20, 0x02, moduleData->afhds3.runPower, 0 }; TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower); putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data)); return true; } - if(moduleData->afhds3.rxFreq != cfg.config.pwmFreq) { - cfg.config.pwmFreq = moduleData->afhds3.rxFreq; - uint8_t data[] = {0x70, 0x17, 0x02, (uint8_t)(moduleData->afhds3.rxFreq & 0xFF), (uint8_t)(moduleData->afhds3.rxFreq >> 8)}; + + //other settings only in 2 way mode (state must be synchronized) + if (this->state != ModuleState::STATE_SYNC_DONE) { + return false; + } + + if (moduleData->afhds3.rxFreq() != cfg.config.pwmFreq) { + cfg.config.pwmFreq = moduleData->afhds3.rxFreq(); + uint8_t data[] = { 0x17, 0x70, 0x02, (uint8_t) (moduleData->afhds3.rxFreq() & 0xFF), (uint8_t) (moduleData->afhds3.rxFreq() >> 8) }; TRACE("AFHDS3 SET RX FREQ"); putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data)); return true; } - PULSE_MODE modelPulseMode = moduleData->afhds3.isPWM() ? PULSE_MODE::PWM: PULSE_MODE::PPM_MODE; - if(modelPulseMode != cfg.config.pulseMode) { + PULSE_MODE modelPulseMode = isPWM(moduleData->subType) ? PULSE_MODE::PWM_MODE : PULSE_MODE::PPM_MODE; + if (modelPulseMode != cfg.config.pulseMode) { cfg.config.pulseMode = modelPulseMode; TRACE("AFHDS3 PWM/PPM %d", modelPulseMode); - uint8_t data[] = {0x70, 0x16, 0x01, (uint8_t)(modelPulseMode)}; + uint8_t data[] = { 0x16, 0x70, 0x01, (uint8_t) (modelPulseMode) }; putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data)); return true; } - SERIAL_MODE modelSerialMode = moduleData->afhds3.isSbus() ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS; - if(modelSerialMode != cfg.config.serialMode) { + SERIAL_MODE modelSerialMode = isSbus(moduleData->subType) ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS; + if (modelSerialMode != cfg.config.serialMode) { cfg.config.serialMode = modelSerialMode; TRACE("AFHDS3 IBUS/SBUS %d", modelSerialMode); - uint8_t data[] = {0x70, 0x18, 0x01, (uint8_t)(modelSerialMode)}; + uint8_t data[] = { 0x18, 0x70, 0x01, (uint8_t) (modelSerialMode) }; putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data)); return true; } - if(moduleData->afhds3.failsafeTimeout != cfg.config.failSafeTimout) { + if (moduleData->afhds3.failsafeTimeout != cfg.config.failSafeTimout) { moduleData->afhds3.failsafeTimeout = cfg.config.failSafeTimout; - uint8_t data[] = { 0x60, 0x12, 0x02, (uint8_t)(moduleData->afhds3.failsafeTimeout & 0xFF), (uint8_t)(moduleData->afhds3.failsafeTimeout >> 8) }; + uint8_t data[] = { 0x12, 0x60, 0x02, (uint8_t) (moduleData->afhds3.failsafeTimeout & 0xFF), (uint8_t) (moduleData->afhds3.failsafeTimeout >> 8) }; putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data)); - TRACE("AFHDS3 TRACE FAILSAFE TMEOUT"); + TRACE("AFHDS3 FAILSAFE TMEOUT, %d", moduleData->afhds3.failsafeTimeout); return true; } - return false; } -void afhds3::sendChannelsData() { +void PulsesData::sendChannelsData() +{ uint8_t channels_start = moduleData->channelsStart; uint8_t channelsCount = 8 + moduleData->channelsCount; uint8_t channels_last = channels_start + channelsCount; + int16_t buffer[MAX_CHANNELS + 1] = { ((MAX_CHANNELS << 8) | CHANNELS_DATA_MODE::CHANNELS), 0 }; - uint8_t channels[2*((8 + moduleData->channelsCount) + 1)]; - channels[0] = 0x01; - channels[1] = channelsCount; - - for(uint8_t channel = channels_start; channel < channels_last; channel++) { - int16_t channelValue = convert(getChannelValue(channel)); - *((int16_t*)(channels + (channel * 2) + 2)) = channelValue; + for (uint8_t channel = channels_start, index = 1; channel < channels_last; channel++, index++) { + int16_t channelValue = convert(::getChannelValue(channel)); + buffer[index] = channelValue; } - putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, channels, sizeof(channels)); + putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, (uint8_t*) buffer, sizeof(buffer)); } -void afhds3::bind(bindCallback_t callback) { - operationCallback = callback; - TRACE("AFHDS3 [BIND]"); - setModelData(); - addToQueue(COMMAND::MODULE_SET_CONFIG, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, cfg.buffer, sizeof(cfg.buffer)); - uint8_t cmd = MODULE_MODE_E::BIND; - addToQueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &cmd, 1); -} - -void afhds3::range(bindCallback_t callback) { - TRACE("AFHDS3 [RANGE CHECK] NOT IMPLEMENTED"); -} - -void afhds3::cancel() { - if(operationCallback!=nullptr) operationCallback(false); - reset(false); -} -void afhds3::stop() { +void PulsesData::stop() +{ TRACE("AFHDS3 STOP"); - uint8_t cmd = MODULE_MODE_E::STANDBY; - putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &cmd, 1); - reset(true); + requestedModuleMode = MODULE_MODE_E::STANDBY; + putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &requestedModuleMode, 1); } - -void afhds3::setToDefault() { - moduleData->afhds3.bindPower = BIND_POWER::MIN_0dbm; - moduleData->afhds3.runPower = RUN_POWER::PLUS_15bBm; - moduleData->afhds3.emi = EMI_STANDARD::FCC; - moduleData->afhds3.telemetry = TELEMETRY::TELEMETRY_ENABLED; - moduleData->afhds3.rxFreq = 50; - moduleData->afhds3.failsafeTimeout = 1000; - moduleData->channelsCount = 14 - 8; - moduleData->failsafeMode = FAILSAFE_HOLD; - //" PWM+i"" PWM+s"" PPM+i"" PPM+s" - moduleData->afhds3.mode = 0; - for (uint8_t channel = 0; channel < MAX_OUTPUT_CHANNELS; channel++) { - failsafeChannels[channel] = 0; - } +void PulsesData::setConfigFromModel() +{ + cfg.config.bindPower = moduleData->afhds3.bindPower; + cfg.config.runPower = getRunPower(); + cfg.config.emiStandard = EMI_STANDARD::FCC; + cfg.config.telemetry = moduleData->afhds3.telemetry; //always use bidirectional mode + cfg.config.pwmFreq = moduleData->afhds3.rxFreq(); + cfg.config.serialMode = isSbus(moduleData->subType) ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS; + cfg.config.pulseMode = isPWM(moduleData->subType) ? PULSE_MODE::PWM_MODE : PULSE_MODE::PPM_MODE; + //use max channels - because channel count can not be changed after bind + cfg.config.channelCount = MAX_CHANNELS; + cfg.config.failSafeTimout = moduleData->afhds3.failsafeTimeout; + setFailSafe(cfg.config.failSafeMode); } -int16_t afhds3::convert(int channelValue) { + +inline int16_t PulsesData::convert(int channelValue) +{ //pulseValue = limit(0, 988 + ((channelValue + 1024) / 2), 0xfff); //988 - 750 = 238 //238 * 20 = 4760 @@ -446,51 +678,29 @@ int16_t afhds3::convert(int channelValue) { // 988 ---- 2012 //-10240 ---- 10240 //-1024 ---- 1024 - return limit(FAILSAFE_MIN, channelValue*10, FAILSAFE_MAX); + return ::limit(FAILSAFE_MIN, channelValue * 10, FAILSAFE_MAX); } -void afhds3::setModelData() { - cfg.config.bindPower = moduleData->afhds3.bindPower; - cfg.config.runPower = moduleData->afhds3.runPower; - cfg.config.emiStandard = moduleData->afhds3.emi; - cfg.config.telemetry = moduleData->afhds3.telemetry; - cfg.config.pwmFreq = moduleData->afhds3.rxFreq; - cfg.config.serialMode = moduleData->afhds3.isSbus() ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS; - cfg.config.pulseMode = moduleData->afhds3.isPWM() ? PULSE_MODE::PWM: PULSE_MODE::PPM_MODE; - cfg.config.channelCount = 8 + moduleData->channelsCount; - cfg.config.failSafeTimout = moduleData->afhds3.failsafeTimeout; - setFailSafe(cfg.config.failSafeMode); -} -uint8_t afhds3::setFailSafe(int16_t* target) { +uint8_t PulsesData::setFailSafe(int16_t* target) +{ int16_t pulseValue = 0; uint8_t channels_start = moduleData->channelsStart; - uint8_t channels_last = channels_start + 8 + moduleData->channelsCount;; + uint8_t channels_last = channels_start + 8 + moduleData->channelsCount; for (uint8_t channel = channels_start; channel < channels_last; channel++) { - if (moduleData->failsafeMode == FAILSAFE_CUSTOM) pulseValue = convert(failsafeChannels[channel]); - else if (moduleData->failsafeMode == FAILSAFE_HOLD) pulseValue = FAILSAFE_KEEP_LAST; - else pulseValue = convert(getChannelValue(channel)); - target[channel-channels_start] = pulseValue; - } - return (uint8_t)(channels_last - channels_start); -} - - -void afhds3::onModelSwitch() { - //uint8_t cmd = MODULE_MODE_E::STANDBY; - //putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &cmd, 1); - //setModelData(); -} - -void afhds3::reset(bool resetFrameCount) { - TRACE("AFHDS3 RESET"); - clearQueue(); - repeatCount = 0; - idleCount = 0; - this->data->state = ModuleState::STATE_NOT_READY; - this->data->frame_index = 1; - this->data->timeout = 0; - this->data->esc_state = 0; + if (moduleData->failsafeMode == FAILSAFE_CUSTOM) { + pulseValue = convert(g_model.failsafeChannels[channel]); + } + else if (moduleData->failsafeMode == FAILSAFE_HOLD) { + pulseValue = FAILSAFE_KEEP_LAST; + } + else { + pulseValue = convert(::getChannelValue(channel)); + } + target[channel - channels_start] = pulseValue; + } + //return max channels because channel count can not be change after bind + return (uint8_t) (MAX_CHANNELS); } } diff --git a/radio/src/pulses/afhds3.h b/radio/src/pulses/afhds3.h index b88ddf3c3..57adf056a 100644 --- a/radio/src/pulses/afhds3.h +++ b/radio/src/pulses/afhds3.h @@ -18,26 +18,174 @@ * GNU General Public License for more details. */ - #ifndef PULSES_AFHDS3_H_ #define PULSES_AFHDS3_H_ -#include "afhds2.h" -#include "../datastructs.h" +#include "libopenui/src/bitfield.h" +#include "definitions.h" +#include "dataconstants.h" +#include "opentx_types.h" +#include "myeeprom.h" +#include "opentx_helpers.h" +#include "pulses_common.h" #include -#include +#include "fifo.h" -#define AFHDS3_BAUDRATE 1500000 -namespace afhds3 { +#define AFHDS_MAX_PULSES 72 +//max number of transitions measured so far 290 + 10% +#define AFHDS_MAX_PULSES_TRANSITIONS 320 +//#define AFHDS3_SLOW -typedef void (*bindCallback_t) (bool); -typedef void (*processSensor_t) (const uint8_t *, uint8_t); -typedef int32_t (*getChannelValue_t)(uint8_t); -enum DeviceAddress { - TRANSMITTER = 0x01, MODULE = 0x03, +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) +#define AFHDS3_BAUDRATE 1500000 +#define AFHDS3_COMMAND_TIMEOUT 5 +#elif !defined(AFHDS3_SLOW) +// 1s = 1 000 000 us +// 1000000/115200 = 8,68 us +// actual timer is ticking in 0,5 us = 8,68*2 = 17,36 because it must be integer take 17 +// difference 1000000 / x = 8.5 --> x = 117 647 = difference = 1.2 % +// allowed half a bit difference on the last bit -- should be fine +#define AFHDS3_BAUDRATE 115200 +//Because timer is ticking with 0.5us +#define BITLEN_AFHDS (17) + +#define AFHDS3_COMMAND_TIMEOUT 15 +#else +// 1000000/57600 = 17,36 us +#define AFHDS3_BAUDRATE 57600 +// 64* 86 = 11 110 +#define AFHDS3_COMMAND_TIMEOUT 20 +#define BITLEN_AFHDS (35) +#endif + +#define AFHDS3_FRAME_HALF_US AFHDS3_COMMAND_TIMEOUT * 2000 + +//get channel value outside of afhds3 namespace +int32_t getChannelValue(uint8_t channel); + +//use uint16_t instead of pulse_duration_t +namespace afhds3 +{ +enum AfhdsSpecialChars +{ + END = 0xC0, //Frame end + START = END, + ESC_END = 0xDC, //Escaped frame end - in case END occurs in fame then ESC ESC_END must be used + ESC = 0xDB, //Escaping character + ESC_ESC = 0xDD, //Escaping character in case ESC occurs in fame then ESC ESC_ESC must be used }; -enum FRAME_TYPE { +struct Data +{ +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) + uint8_t pulses[AFHDS_MAX_PULSES]; + uint8_t * ptr; +#else + uint32_t pulsesSize; + uint16_t pulses[AFHDS_MAX_PULSES_TRANSITIONS]; + uint32_t total; +#endif + + uint8_t frame_index; + uint8_t crc; + uint8_t state; + uint8_t timeout; + uint8_t esc_state; + + void reset() + { +#if !(defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)) + total = 0; + pulsesSize = 0; +#endif + } + +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) + void sendByte(uint8_t b) + { + *ptr++ = b; + } + + const uint8_t* getData() + { + return pulses; + } + + void flush() + { + } +#else + inline void _send_level(uint16_t v) + { + if (pulsesSize >= AFHDS_MAX_PULSES_TRANSITIONS) { + return; + } + pulses[pulsesSize++] = v; + total += v; + } + void sendByte(uint8_t b) + { + if (pulsesSize >= AFHDS_MAX_PULSES_TRANSITIONS) { + return; + } + //use 8n1 + //parity: If the parity is enabled, then the MSB bit of the data to be transmitted is changed by the parity bit + //start is always 0 + bool level = 0; + uint16_t length = BITLEN_AFHDS; //start bit + for (uint8_t i = 0; i <= 8; i++) + { //8 data bits + Stop=1 + bool next_level = b & 1; + if (level == next_level) { + length += BITLEN_AFHDS; + } + else { + _send_level(length); + length = BITLEN_AFHDS; + level = next_level; + } + b = (b >> 1) | 0x80; // shift left to get next bit, fill msb with stop bit - needed just once + } + _send_level(length); //last bit (stop) + + } + //add remaining time of frame + void flush() + { + uint16_t diff = AFHDS3_FRAME_HALF_US - total; + pulses[pulsesSize - 1] += diff; + //ensure 2 ms break + if (pulses[pulsesSize - 1] < 4000) + { + pulses[pulsesSize - 1] = 4050; + } + total += diff; + } + + const uint16_t * getData() + { + return pulses; + } +#endif + + uint32_t getSize() const + { +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) + return ptr - pulses; +#else + return pulsesSize; +#endif + } +}; + +enum DeviceAddress +{ + TRANSMITTER = 0x01, + MODULE = 0x03, +}; + +enum FRAME_TYPE: uint8_t +{ REQUEST_GET_DATA = 0x01, //Get data response: ACK + DATA REQUEST_SET_EXPECT_DATA = 0x02, //Set data response: ACK + DATA REQUEST_SET_EXPECT_ACK = 0x03, //Set data response: ACK @@ -47,7 +195,8 @@ enum FRAME_TYPE { NOT_USED = 0xff }; -enum COMMAND { +enum COMMAND: uint8_t +{ MODULE_READY = 0x01, MODULE_STATE = 0x02, MODULE_MODE = 0x03, @@ -59,13 +208,18 @@ enum COMMAND { COMMAND_RESULT = 0x0D, MODULE_POWER_STATUS = 0x0F, MODULE_VERSION = 0x1F, + VIRTUAL_FAILSAFE = 0x99, // virtual command used to trigger failsafe + UNDEFINED = 0xFF }; -enum COMMAND_DIRECTION { - RADIO_TO_MODULE = 0, MODULE_TO_RADIO = 1 +enum COMMAND_DIRECTION +{ + RADIO_TO_MODULE = 0, + MODULE_TO_RADIO = 1 }; -enum DATA_TYPE { +enum DATA_TYPE +{ READY_DT, // 8 bytes 0x01 Not ready 0x02 Ready STATE_DT, // See MODULE_STATE MODE_DT, @@ -76,14 +230,18 @@ enum DATA_TYPE { MODULE_VERSION_DT, EMPTY_DT, }; + //enum used by command response -> translate to ModuleState -enum MODULE_READY_E { +enum MODULE_READY_E +{ MODULE_STATUS_UNKNOWN = 0x00, MODULE_STATUS_NOT_READY = 0x01, MODULE_STATUS_READY = 0x02 }; -enum ModuleState { +enum ModuleState +{ + STATE_NOT_READY = 0x00, //virtual STATE_HW_ERROR = 0x01, STATE_BINDING = 0x02, STATE_SYNC_RUNNING = 0x03, @@ -94,25 +252,26 @@ enum ModuleState { STATE_UPDATING_RX = 0x08, STATE_UPDATING_RX_FAILED = 0x09, STATE_RF_TESTING = 0x0a, - STATE_NOT_READY = 0x0b, //virtual - STATE_READY = 0x0c, //virtual + STATE_READY = 0x0b, //virtual STATE_HW_TEST = 0xff, }; //used for set command -enum MODULE_MODE_E { +enum MODULE_MODE_E +{ STANDBY = 0x01, BIND = 0x02, //after bind module will enter run mode RUN = 0x03, RX_UPDATE = 0x04, //after successful update module will enter standby mode, otherwise hw error will be raised + MODULE_MODE_UNKNOWN = 0xFF }; -enum CMD_RESULT { +enum CMD_RESULT +{ FAILURE = 0x01, SUCCESS = 0x02, }; - #define MIN_FREQ 50 #define MAX_FREQ 400 #define MAX_CHANNELS 18 @@ -120,39 +279,53 @@ enum CMD_RESULT { #define FAILSAFE_MIN -15000 #define FAILSAFE_MAX 15000 -enum BIND_POWER { +enum BIND_POWER +{ MIN_16dBm = 0x00, + BIND_POWER_FIRST = MIN_16dBm, MIN_5dBm = 0x01, MIN_0dbm = 0x02, PLUS_5dBm = 0x03, - PLUS_14dBm = 0x04 + PLUS_14dBm = 0x04, + BIND_POWER_LAST = PLUS_14dBm, }; -enum RUN_POWER { +enum RUN_POWER +{ PLUS_15bBm = 0x00, + RUN_POWER_FIRST = PLUS_15bBm, PLUS_20bBm = 0x01, PLUS_27dbm = 0x02, PLUS_30dBm = 0x03, - PLUS_33dBm = 0x04 + PLUS_33dBm = 0x04, + RUN_POWER_LAST = PLUS_33dBm, }; -enum EMI_STANDARD { - FCC = 0x00, CE = 0x01 +enum EMI_STANDARD +{ + FCC = 0x00, + CE = 0x01 }; -enum TELEMETRY { - TELEMETRY_DISABLED = 0x00, TELEMETRY_ENABLED = 0x01 +enum TELEMETRY +{ + TELEMETRY_DISABLED = 0x00, + TELEMETRY_ENABLED = 0x01 }; -enum PULSE_MODE { - PWM = 0x00, PPM_MODE = 0x01, +enum PULSE_MODE +{ + PWM_MODE = 0x00, + PPM_MODE = 0x01, }; -enum SERIAL_MODE { - IBUS = 0x00, SBUS_MODE = 0x02 +enum SERIAL_MODE +{ + IBUS = 0x00, + SBUS_MODE = 0x02 }; -struct __attribute__ ((packed)) Config_s { +PACK(struct Config_s { uint8_t bindPower; uint8_t runPower; uint8_t emiStandard; @@ -163,58 +336,75 @@ struct __attribute__ ((packed)) Config_s { uint8_t channelCount; uint16_t failSafeTimout; int16_t failSafeMode[MAX_CHANNELS]; -}; +}); -union Config_u { +union Config_u +{ Config_s config; uint8_t buffer[sizeof(Config_s)]; }; -enum CHANNELS_DATA_MODE { - CHANNELS = 0x01, FAIL_SAFE = 0x02, +enum CHANNELS_DATA_MODE +{ + CHANNELS = 0x01, + FAIL_SAFE = 0x02, }; -struct __attribute__ ((packed)) ChannelsData { +PACK(struct ChannelsData { uint8_t mode; uint8_t channelsNumber; int16_t data[MAX_CHANNELS]; -}; +}); -union ChannelsData_u { +union ChannelsData_u +{ ChannelsData data; uint8_t buffer[sizeof(ChannelsData)]; }; -struct __attribute__ ((packed)) TelemetryData { +PACK(struct TelemetryData +{ uint8_t sensorType; uint8_t length; uint8_t type; uint8_t semsorID; uint8_t data[8]; +}); + +enum MODULE_POWER_SOURCE +{ + INTERNAL = 0x01, + EXTERNAL = 0x02, }; -enum MODULE_POWER_SOURCE { - INTERNAL = 0x01, EXTERNAL = 0x02, -}; - -struct __attribute__ ((packed)) ModuleVersion { +PACK(struct ModuleVersion +{ uint32_t productNumber; uint32_t hardwereVersion; uint32_t bootloaderVersion; uint32_t firmwareVersion; uint32_t rfVersion; -}; +}); +PACK(struct CommandResult_s +{ + uint16_t command; + uint8_t result; + uint8_t respLen; +}); -union AfhdsFrameData { +union AfhdsFrameData +{ uint8_t value; Config_s Config; ChannelsData Channels; TelemetryData Telemetry; ModuleVersion Version; + CommandResult_s CommandResult; }; -struct __attribute__ ((packed)) AfhdsFrame { +PACK(struct AfhdsFrame +{ uint8_t startByte; uint8_t address; uint8_t frameNumber; @@ -222,114 +412,193 @@ struct __attribute__ ((packed)) AfhdsFrame { uint8_t command; uint8_t value; - AfhdsFrameData* GetData() { + AfhdsFrameData * GetData() + { return reinterpret_cast(&value); } -}; +}); #define FRM302_STATUS 0x56 -enum State { +enum State +{ UNKNOWN = 0, SENDING_COMMAND, AWAITING_RESPONSE, IDLE }; -class request { - public: - request(COMMAND command, FRAME_TYPE frameType, const uint8_t* data = nullptr, uint8_t length = 0) { - this->command = command; - this->frameType = frameType; - if(data && length){ - payload = new uint8_t[length]; - std::memcpy(payload, data, length); - } - else payload = nullptr; - payloadSize = length; - } - ~request() { - if(payload != nullptr) { - delete[] payload; - payload = nullptr; - } - } +// one byte frames for request queue +struct Frame +{ enum COMMAND command; enum FRAME_TYPE frameType; - uint8_t* payload; + uint8_t payload; + uint8_t frameNumber; + bool useFrameNumber; uint8_t payloadSize; }; -class afhds3 { -public: - afhds3(FlySkySerialPulsesData* data, ModuleData* moduleData, int16_t* failsafeChannels, getChannelValue_t getChannelValue, processSensor_t processSensor) { - this->data = data; - this->moduleData = moduleData; - this->getChannelValue = getChannelValue; - this->processSensor = processSensor; - this->failsafeChannels = failsafeChannels; - reset(); +// simple fifo implementation because Pulses is used as member of union and can not be non trivial type +struct CommandFifo +{ + Frame commandFifo[8]; + volatile uint32_t setIndex; + volatile uint32_t getIndex; + + void clearCommandFifo(); + + inline uint32_t nextIndex(uint32_t idx) const + { + return (idx + 1) & (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1); } - virtual ~afhds3() { - clearQueue(); + inline uint32_t prevIndex(uint32_t idx) const + { + if (idx == 0) + { + return (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1); + } + return (idx - 1); } - const uint32_t baudrate = AFHDS3_BAUDRATE; - const uint16_t parity = ((uint16_t)0x0000); //USART_Parity_No - const uint16_t stopBits = ((uint16_t)0x0000); //USART_StopBits_1 - const uint16_t wordLength = ((uint16_t)0x0000); //USART_WordLength_8b - const uint16_t commandTimout = 5; //ms + inline bool isEmpty() const + { + return (getIndex == setIndex); + } - void setupPulses(); - void onDataReceived(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize); - void reset(bool resetFrameCount = true); - void bind(bindCallback_t callback); - void range(bindCallback_t callback); - void cancel(); - const char* getState(); - void stop(); - void setToDefault(); - void setModelData(); -private: - const uint8_t FrameAddress = DeviceAddress::TRANSMITTER | (DeviceAddress::MODULE << 4); - const uint16_t commandRepeatCount = 5; - void putByte(uint8_t byte); - void putBytes(uint8_t* data, int length); - void putHeader(COMMAND command, FRAME_TYPE frameType); - void putFooter(); - void putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0); - void addToQueue(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0); - void parseData(uint8_t* rxBuffer, uint8_t rxBufferCount); - void setState(uint8_t state); - bool syncSettings(); - void trace(const char* message); - uint8_t setFailSafe(int16_t* target); - int16_t convert(int channelValue); - void onModelSwitch(); - void sendChannelsData(); - void clearQueue(); + inline void skip() + { + getIndex = nextIndex(getIndex); + } - //external data - FlySkySerialPulsesData* data; - ModuleData* moduleData; - int16_t* failsafeChannels; - int16_t* channelOutputs; - bindCallback_t operationCallback; - getChannelValue_t getChannelValue; - processSensor_t processSensor; - //missing ppm center! + void enqueueACK(COMMAND command, uint8_t frameNumber); + + void enqueue(COMMAND command, FRAME_TYPE frameType, bool useData = false, uint8_t byteContent = 0); - //local config - Config_u cfg; - ModuleVersion version; - enum MODULE_POWER_SOURCE powerSource; - //buffer where the channels are - State operationState; - uint16_t repeatCount; - uint32_t idleCount; - std::queue commandQueue; }; -} +void processTelemetryData(uint8_t module, uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize); + +class PulsesData: public Data, CommandFifo +{ + public: + /** + * Initialize class for operation + * @param moduleIndex index of module one of INTERNAL_MODULE, EXTERNAL_MODULE + * @param resetFrameCount flag if current frame count should be reseted + */ + + void init(uint8_t moduleIndex, bool resetFrameCount = true); + + /** + * Fills DMA buffers with frame to be send depending on actual state + */ + void setupFrame(); + + /** + * Gets actual module status into provided buffer + * @param statusText target buffer for status + */ + void getStatusString(char * statusText) const; + + /** + * Gets actual power source and voltage + */ + void getPowerStatus(char* buffer) const; + + RUN_POWER actualRunPower() const; + + /** + * Sends stop command to prevent any further module operations + */ + void stop(); + + protected: + + void setConfigFromModel(); + + private: + + inline void putBytes(uint8_t* data, int length); + + inline void putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0, uint8_t* frame_index = nullptr); + + void parseData(uint8_t* rxBuffer, uint8_t rxBufferCount); + + void setState(uint8_t state); + + bool syncSettings(); + + void requestInfoAndRun(bool send = false); + + uint8_t setFailSafe(int16_t* target); + + inline int16_t convert(int channelValue); + + void sendChannelsData(); + + void clearFrameData(); + + void processTelemetryData(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize); + + //friendship declaration - use for passing telemetry + friend void processTelemetryData(uint8_t module, uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize); + + /** + * Returns max power that currently can be set - use it to validate before synchronization of settings + */ + RUN_POWER getMaxRunPower() const; + + RUN_POWER getRunPower() const; + + bool isConnectedUnicast(); + + bool isConnectedMulticast(); + + /** + * Index of the module + */ + uint8_t module_index; + /** + * Target mode to be set to the module one of MODULE_MODE_E + */ + uint8_t requestedModuleMode; + /** + * Internal operation state one of UNKNOWN, SENDING_COMMAND, AWAITING_RESPONSE, IDLE + * Used to avoid sending commands when not allowed to + */ + State operationState; + /** + * Actual repeat count for requested command/operation - incremented by every attempt sending anything + */ + uint16_t repeatCount; + /** + * Command count used for counting actual number of commands sent in run mode + */ + uint32_t cmdCount; + /** + * Command index of command to be send when cmdCount reached necessary value + */ + uint32_t cmdIndex; + /** + * Actual power source of the module - should be requested time to time + * Currently requested once + */ + enum MODULE_POWER_SOURCE powerSource; + /** + * Pointer to module config - it is making operations easier and faster + */ + ModuleData* moduleData; + /** + * Actual module configuration - must be requested from module + */ + Config_u cfg; + + /** + * Actual module version - must be requested from module + */ + ModuleVersion version; +}; +} /* Namespace ahfds3 */ #endif /* PULSES_AFHDS3_H_ */ diff --git a/radio/src/pulses/crossfire.cpp b/radio/src/pulses/crossfire.cpp index 5e4ffdb95..cbe4373e4 100644 --- a/radio/src/pulses/crossfire.cpp +++ b/radio/src/pulses/crossfire.cpp @@ -20,8 +20,30 @@ #include "opentx.h" -#define CROSSFIRE_CH_CENTER 0x3E0 #define CROSSFIRE_CH_BITS 11 +#define CROSSFIRE_CENTER 0x3E0 +#if defined(PPM_CENTER_ADJUSTABLE) + #define CROSSFIRE_CENTER_CH_OFFSET(ch) ((2 * limitAddress(ch)->ppmCenter) + 1) // + 1 is for rouding +#else + #define CROSSFIRE_CENTER_CH_OFFSET(ch) (0) +#endif + + +uint8_t createCrossfireModelIDFrame(uint8_t * frame) +{ + uint8_t * buf = frame; + *buf++ = UART_SYNC; /* device address */ + *buf++ = 8; /* frame length */ + *buf++ = COMMAND_ID; /* cmd type */ + *buf++ = MODULE_ADDRESS; /* Destination Address */ + *buf++ = RADIO_ADDRESS; /* Origin Address */ + *buf++ = SUBCOMMAND_CRSF; /* sub command */ + *buf++ = COMMAND_MODEL_SELECT_ID; /* command of set model/receiver id */ + *buf++ = g_model.header.modelId[EXTERNAL_MODULE]; /* model ID */ + *buf++ = crc8_BA(frame + 2, 6); + *buf++ = crc8(frame + 2, 7); + return buf - frame; +} // Range for pulses (channels output) is [-1024:+1024] uint8_t createCrossfireChannelsFrame(uint8_t * frame, int16_t * pulses) @@ -34,7 +56,7 @@ uint8_t createCrossfireChannelsFrame(uint8_t * frame, int16_t * pulses) uint32_t bits = 0; uint8_t bitsavailable = 0; for (int i=0; i= 8) { @@ -60,7 +82,13 @@ void setupPulsesCrossfire() else #endif { - extmodulePulsesData.crossfire.length = createCrossfireChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]); + if (moduleState[EXTERNAL_MODULE].counter == CRSF_FRAME_MODELID) { + extmodulePulsesData.crossfire.length = createCrossfireModelIDFrame(pulses); + moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID_SENT; + } + else { + extmodulePulsesData.crossfire.length = createCrossfireChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]); + } } } } diff --git a/radio/src/pulses/flysky.cpp b/radio/src/pulses/flysky.cpp deleted file mode 100644 index 0b69a4bc7..000000000 --- a/radio/src/pulses/flysky.cpp +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Dedicate for FlySky NV14 board. - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "opentx.h" -#include "flysky.h" - -#define FRAME_TYPE_REQUEST_ACK 0x01 -#define FRAME_TYPE_REQUEST_NACK 0x02 -#define FRAME_TYPE_ANSWER 0x10 -#define IS_VALID_COMMAND_ID(id) ((id) < COMMAND_ID_LAST) - -#ifndef custom_log -#define custom_log -#endif - -#define DEBUG_RF_FRAME_PRINT FRAME_PRINT_OFF -#define FLYSKY_MODULE_TIMEOUT 155 /* ms */ -#define NUM_OF_NV14_CHANNELS (14) -#define VALID_CH_DATA(v) ((v) > 900 && (v) < 2100) - -#define gRomData g_model.moduleData[INTERNAL_MODULE].flysky -#define SET_DIRTY() storageDirty(EE_MODEL) - -#define GET_FLYSKY_PWM_PPM (gRomData.mode < 2 ? FLYSKY_PWM: FLYSKY_PPM) -#define GET_FLYSKY_IBUS_SBUS (gRomData.mode & 1 ? FLYSKY_SBUS: FLYSKY_IBUS) - -typedef struct RX_FLYSKY_IBUS_S { - uint8_t id[2]; - uint8_t channel[2]; -} rx_ibus_t; - -typedef struct FLYSKY_GPS_INFO_S { - uint8_t position_fix; - uint8_t satell_cnt; - uint8_t latitude[4]; - uint8_t longtitude[4]; - uint8_t altitude[4]; - uint8_t g_speed[2]; - uint8_t direction[2]; -} gps_info_t; - -typedef struct FLYSKY_SENSOR_DATA_S { - uint8_t sensor_type; - uint8_t sensor_id; - uint8_t voltage[2]; - uint8_t signal; - uint8_t rssi[2]; - uint8_t noise[2]; - uint8_t snr[2]; - uint8_t temp[2]; - uint8_t ext_voltage[2]; - uint8_t moto_rpm[2]; - uint8_t pressure_value[2]; - gps_info_t gps_info; -} rx_sensor_t; - -typedef struct FLYSKY_FIRMWARE_INFO_S { - uint8_t fw_id[4]; - uint8_t fw_len[4]; - uint8_t hw_rev[4]; - uint8_t fw_rev[4]; - uint8_t fw_pkg_addr[4]; - uint8_t fw_pkg_len[4]; - uint8_t * pkg_data; -} fw_info_t; - -typedef struct RF_INFO_S { - uint8_t id[4]; - uint8_t bind_power; - uint8_t num_of_channel; - uint8_t channel_data_type; - uint8_t protocol; - uint8_t fw_state; // 0: normal, COMMAND_ID0C_UPDATE_RF_FIRMWARE or COMMAND_ID_UPDATE_FIRMWARE_END - fw_info_t fw_info; -} rf_info_t; - -typedef struct RX_INFO_S { - int16_t servo_value[NUM_OF_NV14_CHANNELS]; - rx_ibus_t ibus; - fw_info_t fw_info; -} rx_info_t; - -static rx_sensor_t rx_sensor_info; -static uint8_t tx_working_power = 90; -static uint8_t lastState = FLYSKY_MODULE_STATE_IDLE; -static rf_info_t rf_info = { - .id = {8, 8, 8, 8}, - .bind_power = BIND_NORMAL_POWER, - .num_of_channel = NUM_OF_NV14_CHANNELS, // TODO + g_model.moduleData[port].channelsCount; - .channel_data_type= FLYSKY_CHANNEL_DATA_NORMAL, - .protocol = 0, - .fw_state = 0, - .fw_info = {0} -}; - -static rx_info_t rx_info = { - .servo_value = {1500, 1500, 1500, 1500}, - .ibus = {{0, 0}, - {0, 0}}, - .fw_info = {0} -}; - -/// APIs: ->SetXXXX ->OnXXXX ->GetXXXX -/// For Rx Binding: void onFlySkyBindReceiver(uint8_t port); - -uint16_t getFlySkyReceiverSensorVoltage(uint8_t port, uint16_t * voltage) -{ - uint8_t * flysky_sensor = (uint8_t *) voltage; - uint8_t * ptr = rx_sensor_info.voltage; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = ptr[0]; - flysky_sensor[1] = ptr[1]; - } - - return ptr[1] * 256 + ptr[0]; -} - -uint8_t getFlySkyReceiverSensorSignal(uint8_t port, uint8_t * signal) -{ - uint8_t * flysky_sensor = (uint8_t *) signal; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = rx_sensor_info.signal; - } - - return rx_sensor_info.signal; -} - -uint16_t getFlySkyReceiverSensorRSSI(uint8_t port, uint16_t * rssi) -{ - uint8_t * flysky_sensor = (uint8_t *) rssi; - uint8_t * ptr = rx_sensor_info.rssi; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = ptr[0]; - flysky_sensor[1] = ptr[1]; - } - - return ptr[1] * 256 + ptr[0]; -} - -uint16_t getFlySkyReceiverSensorNoise(uint8_t port, uint16_t * noise) -{ - uint8_t * flysky_sensor = (uint8_t *) noise; - uint8_t * ptr = rx_sensor_info.noise; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = ptr[0]; - flysky_sensor[1] = ptr[1]; - } - - return ptr[1] * 256 + ptr[0]; -} - -uint16_t getFlySkyReceiverSensorSNR(uint8_t port, uint16_t * snr) -{ - uint8_t * flysky_sensor = (uint8_t *) snr; - uint8_t * ptr = rx_sensor_info.snr; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = ptr[0]; - flysky_sensor[1] = ptr[1]; - } - - return ptr[1] * 256 + ptr[0]; -} - -uint16_t getFlySkyReceiverSensorTemperature(uint8_t port, uint16_t * temp) -{ - uint8_t * flysky_sensor = (uint8_t *) temp; - uint8_t * ptr = rx_sensor_info.temp; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = ptr[0]; - flysky_sensor[1] = ptr[1]; - } - - return ptr[1] * 256 + ptr[0]; -} - -uint16_t getFlySkyReceiverSensorExtVoltage(uint8_t port, uint16_t * voltage) -{ - uint8_t * flysky_sensor = (uint8_t *) voltage; - uint8_t * ptr = rx_sensor_info.ext_voltage; - - if (flysky_sensor != NULL) { - flysky_sensor[0] = ptr[0]; - flysky_sensor[1] = ptr[1]; - } - - return ptr[1] * 256 + ptr[0]; -} - - -void getFlySkyReceiverFirmwareRevision(uint8_t port, uint32_t * revision) -{ - uint8_t * fw_info = (uint8_t *) revision; - fw_info[0] = rx_info.fw_info.fw_rev[0]; - fw_info[1] = rx_info.fw_info.fw_rev[1]; - fw_info[2] = rx_info.fw_info.fw_rev[2]; - fw_info[3] = rx_info.fw_info.fw_rev[3]; -} - -void getFlySkyTransmitterFirmwareRevision(uint8_t port, uint32_t * revision) -{ - uint8_t * fw_info = (uint8_t *) revision; - fw_info[0] = rf_info.fw_info.fw_rev[0]; - fw_info[1] = rf_info.fw_info.fw_rev[1]; - fw_info[2] = rf_info.fw_info.fw_rev[2]; - fw_info[3] = rf_info.fw_info.fw_rev[3]; -} - -void getFlySkyFirmwareId(uint8_t port, bool is_receiver, uint32_t * firmware_id) -{ - uint8_t * fw_info = (uint8_t *) firmware_id; - if (is_receiver) { - fw_info[0] = rx_info.fw_info.fw_id[0]; - fw_info[1] = rx_info.fw_info.fw_id[1]; - fw_info[2] = rx_info.fw_info.fw_id[2]; - fw_info[3] = rx_info.fw_info.fw_id[3]; - } - else { - fw_info[0] = rf_info.fw_info.fw_id[0]; - fw_info[1] = rf_info.fw_info.fw_id[1]; - fw_info[2] = rf_info.fw_info.fw_id[2]; - fw_info[3] = rf_info.fw_info.fw_id[3]; - } -} - -void getFlySkyHardwareRevision(uint8_t port, bool is_receiver, uint32_t * revision) -{ - uint8_t * fw_info = (uint8_t *) revision; - if (is_receiver) { - fw_info[0] = rx_info.fw_info.hw_rev[0]; - fw_info[1] = rx_info.fw_info.hw_rev[1]; - fw_info[2] = rx_info.fw_info.hw_rev[2]; - fw_info[3] = rx_info.fw_info.hw_rev[3]; - } - else { - fw_info[0] = rf_info.fw_info.hw_rev[0]; - fw_info[1] = rf_info.fw_info.hw_rev[1]; - fw_info[2] = rf_info.fw_info.hw_rev[2]; - fw_info[3] = rf_info.fw_info.hw_rev[3]; - } -} - -void getFlySkyFirmwareRevision(uint8_t port, bool is_receiver, uint32_t * revision) -{ - if (is_receiver) getFlySkyReceiverFirmwareRevision(port, revision); - else getFlySkyTransmitterFirmwareRevision(port, revision); -} - - -void setFlySkyGetFirmwarePackageAddr(uint8_t port, bool is_receiver, uint32_t * package_address) -{ - uint8_t * fw_package = (uint8_t *) package_address; - if (is_receiver) { - fw_package[0] = rx_info.fw_info.fw_pkg_addr[0]; - fw_package[1] = rx_info.fw_info.fw_pkg_addr[1]; - fw_package[2] = rx_info.fw_info.fw_pkg_addr[2]; - fw_package[3] = rx_info.fw_info.fw_pkg_addr[3]; - } - else { - fw_package[0] = rf_info.fw_info.fw_pkg_addr[0]; - fw_package[1] = rf_info.fw_info.fw_pkg_addr[1]; - fw_package[2] = rf_info.fw_info.fw_pkg_addr[2]; - fw_package[3] = rf_info.fw_info.fw_pkg_addr[3]; - } -} - -void setFlySkyGetFirmwarePackageLen(uint8_t port, bool is_receiver, uint32_t * package_len) -{ - uint8_t * fw_package = (uint8_t *) package_len; - if (is_receiver) { - fw_package[0] = rx_info.fw_info.fw_pkg_len[0]; - fw_package[1] = rx_info.fw_info.fw_pkg_len[1]; - fw_package[2] = rx_info.fw_info.fw_pkg_len[2]; - fw_package[3] = rx_info.fw_info.fw_pkg_len[3]; - } - else { - fw_package[0] = rf_info.fw_info.fw_pkg_len[0]; - fw_package[1] = rf_info.fw_info.fw_pkg_len[1]; - fw_package[2] = rf_info.fw_info.fw_pkg_len[2]; - fw_package[3] = rf_info.fw_info.fw_pkg_len[3]; - } -} - -void setFlySkyGetFirmwarePackageBuffer(uint8_t port, bool is_receiver, uint8_t * buffer) -{ - if (is_receiver) { - rx_info.fw_info.pkg_data = buffer; - } - else { - rf_info.fw_info.pkg_data = buffer; - } -} - - -void setFlySkyTransmitterId(uint8_t port, uint32_t rf_id) -{ - rf_info.id[0] = rf_id & 0xff; - rf_info.id[1] = rf_id & 0xff00 >> 8; - rf_info.id[2] = rf_id & 0xff0000 >> 16; - rf_info.id[3] = rf_id & 0xff000000 >> 24; -} - -void setFlySkyTransmitterProtocol(uint8_t port, uint8_t protocol) -{ - rf_info.protocol = protocol; -} - -void setFlySkyReceiverBindPowerLow(uint8_t port) -{ - rf_info.bind_power = BIND_LOW_POWER; -} - -void setFlySkyReceiverBindPowerNormal(uint8_t port) -{ - rf_info.bind_power = BIND_NORMAL_POWER; -} - -void setFlySkyReceiverChannelCounts(uint8_t port, uint8_t channle_counts) -{ - rf_info.num_of_channel = channle_counts; -} - -void setFlySkyChannelDataFailSafe(uint8_t port) -{ - rf_info.channel_data_type = FLYSKY_CHANNEL_DATA_FAILSAFE; -} - -void setFlySkyChannelDataNormalMode(uint8_t port) -{ - rf_info.channel_data_type = FLYSKY_CHANNEL_DATA_NORMAL; -} - -void setFlySkyChannelOutputs(int channel, int16_t outValue) -{ - channelOutputs[channel] = outValue; -} - -static uint32_t set_loop_cnt = 0; - -void setFlySkyChannelData(int channel, int16_t servoValue) -{ - if (channel < NUM_OF_NV14_CHANNELS && VALID_CH_DATA(servoValue)) { - rx_info.servo_value[channel] = (1000 * (servoValue + 1024) / 2048) + 1000; - } - - if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY) && (set_loop_cnt++ % 1000 == 0)) { - TRACE_NOCRLF("HALL(%0d): ", FLYSKY_HALL_BAUDRATE); - for (int idx = 0; idx < NUM_OF_NV14_CHANNELS; idx++) { - TRACE_NOCRLF("CH%0d:%0d ", idx + 1, rx_info.servo_value[idx]); - } - TRACE(" "); - } -} - -void sendPulsesFrameByState(uint8_t port, uint8_t frameState) -{ - intmodulePulsesData.flysky.state = frameState; - intmodulePulsesData.flysky.timeout = FLYSKY_MODULE_TIMEOUT; - //setupPulsesFlySky(port); // effect immediately -} - - -bool isRxBindingState(uint8_t port) -{ - return moduleState[port].mode == MODULE_MODE_BIND; -} - -bool isFlySkyUsbDownload(void) -{ - return rf_info.fw_state != 0; -} - -void onIntmoduleSetPower(bool isPowerOn) -{ - if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) TRACE("RF Power %s", isPowerOn != 0 ? "ON" : "OFF"); - - if (isPowerOn) { - INTERNAL_MODULE_ON(); - } - else { - INTERNAL_MODULE_OFF(); - } -} -//REMOVED FROM OPENTX -void resetPulsesFlySky(uint8_t port); - -void onIntmoduleBindReceiver(uint8_t port) -{ - resetPulsesFlySky(port); - moduleState[port].mode = MODULE_MODE_BIND; - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT; -} - -void onFlySkyReceiverPulseMode(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_PWM_PPM; -} - -void onFlySkyReceiverPulsePort(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS; -} - -void onIntmoduleReceiverSetFrequency(uint8_t port) -{ - sendPulsesFrameByState(port, FLYSKY_MODULE_STATE_SET_RX_FREQUENCY); -} - -void onIntmoduleReceiverSetPulse(uint8_t port, uint8_t mode_and_port) // mode_and_port = 0,1,2,3 -{ - if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) TRACE("PulseMode+Port: %0d", mode_and_port); - sendPulsesFrameByState(port, FLYSKY_MODULE_STATE_SET_RX_PWM_PPM); -} - -void onFlySkyTransmitterPower(uint8_t port, uint8_t dBmValue) -{ - tx_working_power = dBmValue; - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_TX_POWER; -} - - -void onFlySkyUpdateReceiverFirmwareStart(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_UPDATE_RX_FIRMWARE; -} -void setFlyskyState(uint8_t port, uint8_t state) { - intmodulePulsesData.flysky.state = state; -} - -void onIntmoduleUsbDownloadStart(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE; -} - -void onFlySkyUsbDownloadStart(uint8_t fw_state) -{ - rf_info.fw_state = fw_state; -} -void onFlySkyGetVersionInfoStart(uint8_t port, uint8_t isRfTransfer) -{ - lastState = intmodulePulsesData.flysky.state; - if ( isRfTransfer != 0 ) - setFlyskyState(port, FLYSKY_MODULE_STATE_GET_RF_FW_VERSION); - else setFlyskyState(port, FLYSKY_MODULE_STATE_GET_RX_FW_VERSION); -} -void onFlySkyUpdateTransmitterProtocol(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_UPDATE_RF_PROTOCOL; -} - - -void onFlySkyGetReceiverFirmwareInfo(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RX_FIRMWARE_INFO; -} - -void onFlySkyGetTransmitterFirmwareInfo(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RF_FIRMWARE_INFO; -} - -void onFlySkyGetReceiverFirmwareVersion(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RX_FW_VERSION; -} - -void onFlySkyGetTransmitterFirmwareVersion(uint8_t port) -{ - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RF_FW_VERSION; -} - -void initFlySkyArray(uint8_t port) -{ - intmodulePulsesData.flysky.ptr = intmodulePulsesData.flysky.pulses; - intmodulePulsesData.flysky.crc = 0; -} - -inline void putFlySkyByte(uint8_t port, uint8_t byte) -{ - if (END == byte) { - *intmodulePulsesData.flysky.ptr++ = ESC; - *intmodulePulsesData.flysky.ptr++ = ESC_END; - } - else if (ESC == byte) { - *intmodulePulsesData.flysky.ptr++ = ESC; - *intmodulePulsesData.flysky.ptr++ = ESC_ESC; - } - else { - *intmodulePulsesData.flysky.ptr++ = byte; - } -} - -void putFlySkyFrameByte(uint8_t port, uint8_t byte) -{ - intmodulePulsesData.flysky.crc += byte; - putFlySkyByte(port, byte); -} - -void putFlySkyFrameHead(uint8_t port) -{ - *intmodulePulsesData.flysky.ptr++ = END; -} - -void putFlySkyFrameIndex(uint8_t port) -{ - putFlySkyFrameByte(port, intmodulePulsesData.flysky.frame_index); -} - -void putFlySkyFrameCrc(uint8_t port) -{ - putFlySkyByte(port, intmodulePulsesData.flysky.crc ^ 0xff); -} - -void putFlySkyFrameTail(uint8_t port) -{ - *intmodulePulsesData.flysky.ptr++ = END; -} - - -void putFlySkyRfInit(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_RF_INIT); -} - -void putFlySkyBindReceiver(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_BIND); - putFlySkyFrameByte(port, rf_info.bind_power); - putFlySkyFrameByte(port, rf_info.id[0]); - putFlySkyFrameByte(port, rf_info.id[1]); - putFlySkyFrameByte(port, rf_info.id[2]); - putFlySkyFrameByte(port, rf_info.id[3]); -} - -void putFlySkySetReceiverID(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_SET_RECEIVER_ID); - putFlySkyFrameByte(port, gRomData.rx_id[0]); // receiver ID (byte 0) - putFlySkyFrameByte(port, gRomData.rx_id[1]); // receiver ID (byte 1) - putFlySkyFrameByte(port, gRomData.rx_id[2]); // receiver ID (byte 2) - putFlySkyFrameByte(port, gRomData.rx_id[3]); // receiver ID (byte 3) -} - -void putFlySkyGetReceiverConfig(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_ANSWER); - putFlySkyFrameByte(port, COMMAND_ID_RF_GET_CONFIG); - putFlySkyFrameByte(port, GET_FLYSKY_PWM_PPM); // 00:PWM, 01:PPM - putFlySkyFrameByte(port, GET_FLYSKY_IBUS_SBUS);// 00:I-BUS, 01:S-BUS - putFlySkyFrameByte(port, gRomData.rx_freq[0] < 50 ? 50 : gRomData.rx_freq[0]); // receiver servo freq bit[7:0] - putFlySkyFrameByte(port, gRomData.rx_freq[1]); // receiver servo freq bit[15:8] -} - -void putFlySkySetReceiverPulseMode(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_SET_RX_PWM_PPM); - putFlySkyFrameByte(port, GET_FLYSKY_PWM_PPM); // 00:PWM, 01:PPM -} - -void putFlySkySetReceiverPort(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_SET_RX_IBUS_SBUS); - putFlySkyFrameByte(port, GET_FLYSKY_IBUS_SBUS); // 0x00:I-BUS, 0x01:S-BUS -} - -void putFlySkySetReceiverServoFreq(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_SET_RX_SERVO_FREQ); - putFlySkyFrameByte(port, gRomData.rx_freq[0]); // receiver servo freq bit[7:0] - putFlySkyFrameByte(port, gRomData.rx_freq[1]); // receiver servo freq bit[15:8] -} - -void putFlySkyGetFirmwareInfo(uint8_t port, uint8_t fw_word) -{ -#ifdef RF_PROTOCOL_V13 - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_GET_FIRMWARE_INFO); - putFlySkyFrameByte(port, fw_word); // 0x00:RX firmware, 0x01:RF firmware -#endif -} - -void putFlySkySetPowerdBm(uint8_t port, uint8_t dBm) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID0D_SET_TX_POWER); - putFlySkyFrameByte(port, dBm); // 0x00:RX firmware, 0x01:RF firmware -} - -void putFlySkyGetFirmwareVersion(uint8_t port, uint8_t fw_word) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_GET_FIRMWARE_REV); - putFlySkyFrameByte(port, fw_word); // 0x00:RX firmware, 0x01:RF firmware -} - -void putFlySkySendChannelData(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_NACK); - putFlySkyFrameByte(port, COMMAND_ID_SEND_CHANNEL_DATA); - - if (0 /* TODO send failsafe*/) { - putFlySkyFrameByte(port, 0x01); - uint8_t channels_start = g_model.moduleData[port].channelsStart; - uint8_t channels_count = min(NUM_OF_NV14_CHANNELS, channels_start + 8 + g_model.moduleData[port].channelsCount); - putFlySkyFrameByte(port, channels_count); - for (uint8_t channel = channels_start; channel < channels_count; channel++) { - int16_t failsafeValue = g_model.failsafeChannels[channel]; - uint16_t pulseValue = limit(900, 900 + ((2100 - 900) * (failsafeValue + 1024) / 2048), 2100); - putFlySkyFrameByte(port, pulseValue & 0xff); - putFlySkyFrameByte(port, pulseValue >> 8); - } - } - else { - putFlySkyFrameByte(port, 0x00); - uint8_t channels_start = g_model.moduleData[port].channelsStart; - uint8_t channels_count = min(NUM_OF_NV14_CHANNELS, channels_start + 8 + g_model.moduleData[port].channelsCount); - putFlySkyFrameByte(port, channels_count); - for (uint8_t channel = channels_start; channel < channels_count; channel++) { - int channelValue = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; - uint16_t pulseValue = limit(900, 900 + ((2100 - 900) * (channelValue + 1024) / 2048), 2100); - putFlySkyFrameByte(port, pulseValue & 0xff); - putFlySkyFrameByte(port, pulseValue >> 8); - } - } -} - -void putFlySkyUpdateFirmwareStart(uint8_t port, uint8_t fw_word) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - if (fw_word == FLYSKY_RX_FIRMWARE) { - fw_word = COMMAND_ID20_UPDATE_RX_FIRMWARE; - } - else { - fw_word = COMMAND_ID0C_UPDATE_RF_FIRMWARE; - } - putFlySkyFrameByte(port, fw_word); // 0x00:RX firmware, 0x01:RF firmware -} - -void putFlySkyUpdateRfProtocol(uint8_t port) -{ - putFlySkyFrameByte(port, FRAME_TYPE_REQUEST_ACK); - putFlySkyFrameByte(port, COMMAND_ID_SET_RF_PROTOCOL); - putFlySkyFrameByte(port, rf_info.protocol); // 0x00:AFHDS1 0x01:AFHDS2 0x02:AFHDS2A -} - - -void incrFlySkyFrame(uint8_t port) -{ - if (++intmodulePulsesData.flysky.frame_index == 0) - intmodulePulsesData.flysky.frame_index = 1; -} - -bool checkFlySkyFrameCrc(const uint8_t * ptr, uint8_t size) -{ - uint8_t crc = 0; - - for (uint8_t i = 0; i < size; i++) { - crc += ptr[i]; - } - - if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) { - if (ptr[2] != 0x06 || (set_loop_cnt++ % 100 == 0)) { - TRACE_NOCRLF("RF(%0d): C0", INTERNAL_MODULE_BAUDRATE); - for (int idx = 0; idx <= size; idx++) { - TRACE_NOCRLF(" %02X", ptr[idx]); - } - TRACE(" C0;"); - - if ((crc ^ 0xff) != ptr[size]) { - TRACE("ErrorCRC %02X especting %02X", crc ^ 0xFF, ptr[size]); - } - } - } - - return (crc ^ 0xff) == ptr[size]; -} - -void parseFlySkyFeedbackFrame(uint8_t port) -{ - const uint8_t * ptr = intmodulePulsesData.flysky.telemetry; - if (*ptr++ != END) - return; - - uint8_t frame_number = *ptr++; - uint8_t frame_type = *ptr++; - uint8_t command_id = *ptr++; - uint8_t first_para = *ptr++; - uint8_t * p_data = NULL; - - if (!checkFlySkyFrameCrc(intmodulePulsesData.flysky.telemetry + 1, intmodulePulsesData.flysky.telemetry_index - 2)) { - return; - } - - switch (command_id) { - default: - if (moduleState[port].mode == MODULE_MODE_NORMAL - && intmodulePulsesData.flysky.state >= FLYSKY_MODULE_STATE_IDLE) { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT; - if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) TRACE("State back to channel data"); - } - break; - - case COMMAND_ID_RF_INIT: { - if (first_para == 0x01) { // action only RF ready - - if (moduleState[port].mode == MODULE_MODE_BIND) { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_BIND; - incrFlySkyFrame(port); - } - - /*else if (moduleState[port].mode == MODULE_MODE_RANGECHECK) { - - }*/ - - if (intmodulePulsesData.flysky.state == FLYSKY_MODULE_STATE_INIT) { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RECEIVER_ID; - incrFlySkyFrame(port); - } - } - else intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_IDLE; - break; - } - - case COMMAND_ID_BIND: { - if (frame_type != FRAME_TYPE_ANSWER) { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_IDLE; - return; - } - g_model.header.modelId[port] = ptr[2]; - gRomData.rx_id[0] = first_para; - gRomData.rx_id[1] = *ptr++; - gRomData.rx_id[2] = *ptr++; - gRomData.rx_id[3] = *ptr++; - if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) - TRACE("New Rx ID: %02X %02X %02X %02X", gRomData.rx_id[0], gRomData.rx_id[1], gRomData.rx_id[2], gRomData.rx_id[3]); - SET_DIRTY(); - resetPulsesFlySky(port); - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT; - break; - - case COMMAND_ID_RF_GET_CONFIG: - intmodulePulsesData.flysky.frame_index = frame_number; - sendPulsesFrameByState(port, FLYSKY_MODULE_STATE_GET_RECEIVER_CONFIG); - break; - } - - case COMMAND_ID_RX_SENSOR_DATA: { - // rx_sensor_info.sensor_id = *ptr++; // TBC: in protocol doc, but no such byte in sample data - if (first_para == FLYSKY_SENSOR_RX_VOLTAGE) { - rx_sensor_info.voltage[0] = *ptr++; - rx_sensor_info.voltage[1] = *ptr++; - } - - else if (first_para == FLYSKY_SENSOR_GPS) { - p_data = &rx_sensor_info.gps_info.position_fix; - for (int idx = 17; idx > 0; idx--) { - *p_data++ = *ptr++; - } - } - - else if (first_para == FLYSKY_SENSOR_RX_SIGNAL) { - rx_sensor_info.signal = *ptr++; - } - - else if (first_para > FLYSKY_SENSOR_RX_SIGNAL && first_para < FLYSKY_SENSOR_GPS) { - p_data = rx_sensor_info.rssi + (first_para - FLYSKY_SENSOR_RX_RSSI) * 2; - p_data[0] = *ptr++; - p_data[1] = *ptr++; - } - - if (moduleState[port].mode == MODULE_MODE_RANGECHECK) { - moduleState[port].mode = MODULE_MODE_NORMAL; - onFlySkyTransmitterPower(port, 0); // set power 0 - break; - } - - if (moduleState[port].mode == MODULE_MODE_NORMAL && intmodulePulsesData.flysky.state >= FLYSKY_MODULE_STATE_IDLE) { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT; - } - break; - } - - case COMMAND_ID_SET_RECEIVER_ID: { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT; - return; - } - - case COMMAND_ID0D_SET_TX_POWER: { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT; - break; - } - - case COMMAND_ID_SET_RX_PWM_PPM: { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS; - break; - } - - case COMMAND_ID_SET_RX_IBUS_SBUS: { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_FREQUENCY; - break; - } - - case COMMAND_ID_SET_RX_SERVO_FREQ: { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT; - break; - } - - case COMMAND_ID0C_UPDATE_RF_FIRMWARE: { - rf_info.fw_state = FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE; - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_IDLE; - break; - } - } -} - -extern uint8_t intmoduleGetByte(uint8_t * byte); - -static STRUCT_HALL rfProtocolRx = {0}; -static uint32_t rfRxCount = 0; - -bool isRfProtocolRxMsgOK(void) -{ - bool isMsgOK = (0 != rfRxCount); - rfRxCount = 0; - return isMsgOK && isFlySkyUsbDownload(); -} - -#if !defined(SIMU) -void checkFlySkyFeedback(uint8_t port) -{ - uint8_t byte; - - while (intmoduleGetByte(&byte)) { - //if ( intmodulePulsesData.flysky.state == FLYSKY_MODULE_STATE_IDLE - // && rf_info.fw_state == FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE ) - { - Parse_Character(&rfProtocolRx, byte ); - if ( rfProtocolRx.msg_OK ) - { - rfRxCount++; - rfProtocolRx.msg_OK = 0; - uint8_t *pt = (uint8_t*)&rfProtocolRx; - pt[rfProtocolRx.length + 3] = rfProtocolRx.checkSum & 0xFF; - pt[rfProtocolRx.length + 4] = rfProtocolRx.checkSum >> 8; - - if((DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY)) { - TRACE("RF: %02X %02X %02X ...%04X; CRC:%04X", pt[0], pt[1], pt[2], - rfProtocolRx.checkSum, calc_crc16(pt, rfProtocolRx.length+3)); - } - - if ( 0x01 == rfProtocolRx.length && - ( 0x05 == rfProtocolRx.data[0] || 0x06 == rfProtocolRx.data[0]) ) - { - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT; - rf_info.fw_state = 0; - } - - usbDownloadTransmit(pt, rfProtocolRx.length + 5); - } - //continue; - } - - if (byte == END && intmodulePulsesData.flysky.telemetry_index > 0) { - parseFlySkyFeedbackFrame(port); - intmodulePulsesData.flysky.telemetry_index = 0; - } - else { - if (byte == ESC) { - intmodulePulsesData.flysky.esc_state = 1; - } - else { - if (intmodulePulsesData.flysky.esc_state) { - intmodulePulsesData.flysky.esc_state = 0; - if (byte == ESC_END) - byte = END; - else if (byte == ESC_ESC) - byte = ESC; - } - intmodulePulsesData.flysky.telemetry[intmodulePulsesData.flysky.telemetry_index++] = byte; - if (intmodulePulsesData.flysky.telemetry_index >= sizeof(intmodulePulsesData.flysky.telemetry)) { - // TODO buffer is full, log an error? - intmodulePulsesData.flysky.telemetry_index = 0; - } - } - } - } -} -#endif - -void resetPulsesFlySky(uint8_t port) -{ - intmodulePulsesData.flysky.frame_index = 1; - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_TX_POWER; - intmodulePulsesData.flysky.timeout = 0; - intmodulePulsesData.flysky.esc_state = 0; - moduleState[port].mode = MODULE_MODE_NORMAL; - uint16_t rx_freq = g_model.moduleData[port].flysky.rx_freq[0]; - rx_freq += (g_model.moduleData[port].flysky.rx_freq[1] * 256); - if (50 > rx_freq || 400 < rx_freq) { - g_model.moduleData[port].flysky.rx_freq[0] = 50; - } -} - -void setupPulsesFlySky(uint8_t port) -{ -#if !defined(SIMU) - checkFlySkyFeedback(port); -#endif - - initFlySkyArray(port); - putFlySkyFrameHead(port); - putFlySkyFrameIndex(port); - - if (intmodulePulsesData.flysky.state < FLYSKY_MODULE_STATE_DEFAULT) { - - if (++intmodulePulsesData.flysky.timeout >= FLYSKY_MODULE_TIMEOUT / 9) { - - intmodulePulsesData.flysky.timeout = 0; - - switch (intmodulePulsesData.flysky.state) { - - case FLYSKY_MODULE_STATE_INIT: - putFlySkyRfInit(port); - break; - - case FLYSKY_MODULE_STATE_BIND: - putFlySkyBindReceiver(port); - break; - - case FLYSKY_MODULE_STATE_SET_RECEIVER_ID: - putFlySkySetReceiverID(port); - break; - - case FLYSKY_MODULE_STATE_GET_RECEIVER_CONFIG: - putFlySkyGetReceiverConfig(port); - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT; - break; - - case FLYSKY_MODULE_STATE_SET_TX_POWER: - putFlySkySetPowerdBm(port, tx_working_power); - break; - - case FLYSKY_MODULE_STATE_SET_RX_PWM_PPM: - putFlySkySetReceiverPulseMode(port); - break; - - case FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS: - putFlySkySetReceiverPort(port); - break; - - case FLYSKY_MODULE_STATE_SET_RX_FREQUENCY: - putFlySkySetReceiverServoFreq(port); - break; - - case FLYSKY_MODULE_STATE_UPDATE_RF_PROTOCOL: - putFlySkyUpdateRfProtocol(port); - break; - - case FLYSKY_MODULE_STATE_UPDATE_RX_FIRMWARE: - putFlySkyUpdateFirmwareStart(port, FLYSKY_RX_FIRMWARE); - break; - - case FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE: - putFlySkyUpdateFirmwareStart(port, FLYSKY_RF_FIRMWARE); - break; - - case FLYSKY_MODULE_STATE_GET_RX_FIRMWARE_INFO: - putFlySkyGetFirmwareInfo(port, FLYSKY_RX_FIRMWARE); - break; - - case FLYSKY_MODULE_STATE_GET_RF_FIRMWARE_INFO: - putFlySkyGetFirmwareInfo(port, FLYSKY_RF_FIRMWARE); - break; - - case FLYSKY_MODULE_STATE_GET_RX_FW_VERSION: - putFlySkyGetFirmwareVersion(port, FLYSKY_RX_FIRMWARE); - break; - - case FLYSKY_MODULE_STATE_GET_RF_FW_VERSION: - putFlySkyGetFirmwareVersion(port, FLYSKY_RF_FIRMWARE); - break; - - case FLYSKY_MODULE_STATE_IDLE: - intmodulePulsesData.flysky.ptr = intmodulePulsesData.flysky.pulses; - return; - - default: - intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT; - initFlySkyArray(port); - if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) { - TRACE("State back to INIT\r\n"); - } - return; - } - } - else { - initFlySkyArray(port); - return; - } - } - else { - putFlySkySendChannelData(port); - incrFlySkyFrame(port); - } - - putFlySkyFrameCrc(port); - putFlySkyFrameTail(port); - - if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) { - /* print each command, except channel data by interval */ - uint8_t * data = intmodulePulsesData.flysky.pulses; - if (data[3] != COMMAND_ID_SEND_CHANNEL_DATA || (set_loop_cnt++ % 100 == 0)) { - uint8_t size = intmodulePulsesData.flysky.ptr - data; - TRACE_NOCRLF("TX(State%0d)%0dB:", intmodulePulsesData.flysky.state, size); - for (int idx = 0; idx < size; idx++) { - TRACE_NOCRLF(" %02X", data[idx]); - } - TRACE(";"); - } - } -} - -#if !defined(SIMU) -void usbDownloadTransmit(uint8_t *buffer, uint32_t size) -{ - for (int idx = 0; idx < size; idx++) - { - usbSerialPutc(buffer[idx]); - } -} -#endif diff --git a/radio/src/pulses/flysky.h b/radio/src/pulses/flysky.h deleted file mode 100644 index 75df3ee0d..000000000 --- a/radio/src/pulses/flysky.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _PULSES_FLYSKY_H_ -#define _PULSES_FLYSKY_H_ -#include "afhds2.h" - -/* -#define END 0xC0 -#define ESC 0xDB -#define ESC_END 0xDC -#define ESC_ESC 0xDD -*/ - -enum FlySkyModuleCommandID { - COMMAND_ID_NONE, - COMMAND_ID_RF_INIT, - COMMAND_ID_BIND, - COMMAND_ID_SET_RECEIVER_ID, - COMMAND_ID_RF_GET_CONFIG, - COMMAND_ID_SEND_CHANNEL_DATA, - COMMAND_ID_RX_SENSOR_DATA, - COMMAND_ID_SET_RX_PWM_PPM, - COMMAND_ID_SET_RX_SERVO_FREQ, - COMMAND_ID_GET_FIRMWARE_REV, - COMMAND_ID_SET_RX_IBUS_SBUS, - COMMAND_ID_SET_RX_IBUS_SERVO_EXT, - COMMAND_ID0C_UPDATE_RF_FIRMWARE = 0x0C, - COMMAND_ID0D_SET_TX_POWER = 0x0D, - COMMAND_ID_SET_RF_PROTOCOL, - COMMAND_ID_TEST_RANGE, - COMMAND_ID_TEST_RF_RESERVED, - COMMAND_ID20_UPDATE_RX_FIRMWARE = 0x20, - COMMAND_ID_LAST -}; - -enum FlySkySensorType_E { - FLYSKY_SENSOR_RX_VOLTAGE, - FLYSKY_SENSOR_RX_SIGNAL, - FLYSKY_SENSOR_RX_RSSI, - FLYSKY_SENSOR_RX_NOISE, - FLYSKY_SENSOR_RX_SNR, - FLYSKY_SENSOR_TEMP, - FLYSKY_SENSOR_EXT_VOLTAGE, - FLYSKY_SENSOR_MOTO_RPM, - FLYSKY_SENSOR_PRESURRE, - FLYSKY_SENSOR_GPS -}; - -enum FlySkyModuleState_E { - FLYSKY_MODULE_STATE_SET_TX_POWER, - FLYSKY_MODULE_STATE_INIT, - FLYSKY_MODULE_STATE_BIND, - FLYSKY_MODULE_STATE_SET_RECEIVER_ID, - FLYSKY_MODULE_STATE_SET_RX_PWM_PPM, - FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS, - FLYSKY_MODULE_STATE_SET_RX_FREQUENCY, - FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE, - FLYSKY_MODULE_STATE_UPDATE_RX_FIRMWARE, - FLYSKY_MODULE_STATE_UPDATE_HALL_FIRMWARE, - FLYSKY_MODULE_STATE_UPDATE_RF_PROTOCOL, - FLYSKY_MODULE_STATE_GET_RECEIVER_CONFIG, - FLYSKY_MODULE_STATE_GET_RX_FIRMWARE_INFO, - FLYSKY_MODULE_STATE_GET_RX_FW_VERSION, - FLYSKY_MODULE_STATE_GET_RF_FIRMWARE_INFO, - FLYSKY_MODULE_STATE_GET_RF_FW_VERSION, - FLYSKY_MODULE_STATE_IDLE, - FLYSKY_MODULE_STATE_DEFAULT, -}; - -enum FlySkyBindState_E { - BIND_LOW_POWER, - BIND_NORMAL_POWER, - BIND_EXIT, -}; - -enum FlySkyRxPulse_E { - FLYSKY_PWM, - FLYSKY_PPM -}; - -enum FlySkyRxPort_E { - FLYSKY_IBUS, - FLYSKY_SBUS -}; - -enum FlySkyFirmwareType_E { - FLYSKY_RX_FIRMWARE, - FLYSKY_RF_FIRMWARE -}; - -enum FlySkyChannelDataType_E { - FLYSKY_CHANNEL_DATA_NORMAL, - FLYSKY_CHANNEL_DATA_FAILSAFE -}; - -enum FlySkyPulseModeValue_E { - PWM_IBUS, PWM_SBUS, - PPM_IBUS, PPM_SBUS -}; - -enum DEBUG_RF_FRAME_PRINT_E { - FRAME_PRINT_OFF,// 0:OFF, 1:RF frame only, 2:TX frame only, 3:Both RF and TX frame - RF_FRAME_ONLY, - TX_FRAME_ONLY, - BOTH_FRAME_PRINT -}; - - -void setFlyskyState(uint8_t port, uint8_t state); -void onFlySkyBindReceiver(uint8_t port); -void onFlySkyModuleSetPower(uint8_t port, bool isPowerOn); -void onFlySkyGetVersionInfoStart(uint8_t port, uint8_t isRfTransfer); -void usbDownloadTransmit(uint8_t *buffer, uint32_t size); -#endif diff --git a/radio/src/pulses/ghost.cpp b/radio/src/pulses/ghost.cpp new file mode 100755 index 000000000..478202b57 --- /dev/null +++ b/radio/src/pulses/ghost.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" + +// Range for pulses (channels output) is [-1024:+1024] +uint8_t createGhostChannelsFrame(uint8_t * frame, int16_t * pulses) +{ + static uint8_t lastGhostFrameId = GHST_UL_RC_CHANS_HS4_5TO8; + uint8_t ghostUpper4Offset = 0; + + switch (lastGhostFrameId) { + case GHST_UL_RC_CHANS_HS4_5TO8: + ghostUpper4Offset = 0; + break; + case GHST_UL_RC_CHANS_HS4_9TO12: + ghostUpper4Offset = 4; + break; + case GHST_UL_RC_CHANS_HS4_13TO16: + ghostUpper4Offset = 8; + break; + } + + uint8_t * buf = frame; +#if SPORT_MAX_BAUDRATE < 400000 + *buf++ = g_eeGeneral.telemetryBaudrate == GHST_TELEMETRY_RATE_400K ? GHST_ADDR_MODULE_SYM : GHST_ADDR_MODULE_ASYM; +#else + *buf++ = GHST_ADDR_MODULE_SYM; +#endif + *buf++ = GHST_UL_RC_CHANS_SIZE; + uint8_t * crc_start = buf; + *buf++ = lastGhostFrameId; + + // first 4 high speed, 12 bit channels (11 relevant bits with openTx) + uint32_t bits = 0; + uint8_t bitsavailable = 0; + for (int i = 0; i < 4; i++) { + uint32_t value = limit(0, GHST_RC_CTR_VAL_12BIT + (((pulses[i]) << 3) / 5), 2 * GHST_RC_CTR_VAL_12BIT); + bits |= value << bitsavailable; + bitsavailable += GHST_CH_BITS_12; + while (bitsavailable >= 8) { + *buf++ = bits; + bits >>= 8; + bitsavailable -= 8; + } + } + + // second 4 lower speed, 8 bit channels + for (int i = 4; i < 8; ++i) { + *buf++ = limit(0, GHST_RC_CTR_VAL_8BIT + (((pulses[i + ghostUpper4Offset]) >> 1) / 5), 2 * GHST_RC_CTR_VAL_8BIT); + } + + *buf++ = crc8(crc_start, GHST_UL_RC_CHANS_SIZE - 1); + + switch (lastGhostFrameId) { + case GHST_UL_RC_CHANS_HS4_5TO8: + lastGhostFrameId = GHST_UL_RC_CHANS_HS4_9TO12; + break; + case GHST_UL_RC_CHANS_HS4_9TO12: + lastGhostFrameId = GHST_UL_RC_CHANS_HS4_13TO16; + break; + case GHST_UL_RC_CHANS_HS4_13TO16: + lastGhostFrameId = GHST_UL_RC_CHANS_HS4_5TO8; + break; + } + + return buf - frame; +} + +void setupPulsesGhost() +{ + if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) { + uint8_t * pulses = extmodulePulsesData.ghost.pulses; + extmodulePulsesData.ghost.length = createGhostChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]); + } +} diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h index 313e034bd..0ddf2477a 100644 --- a/radio/src/pulses/modules_constants.h +++ b/radio/src/pulses/modules_constants.h @@ -29,15 +29,15 @@ enum ModuleType { MODULE_TYPE_DSM2, MODULE_TYPE_CROSSFIRE, MODULE_TYPE_MULTIMODULE, - MODULE_TYPE_R9M_PXX1, - MODULE_TYPE_R9M_PXX2, - MODULE_TYPE_R9M_LITE_PXX1, - MODULE_TYPE_R9M_LITE_PXX2, - MODULE_TYPE_R9M_LITE_PRO_PXX1, // Doesn't exist + MODULE_TYPE_R9M_PXX1, // R9M + MODULE_TYPE_R9M_PXX2, // R9M ACCESS + MODULE_TYPE_R9M_LITE_PXX1, //R9MLite + MODULE_TYPE_R9M_LITE_PXX2, //R9MLP + MODULE_TYPE_GHOST, // Replaces MODULE_TYPE_R9M_LITE_PRO_PXX1 which doesn't exist MODULE_TYPE_R9M_LITE_PRO_PXX2, MODULE_TYPE_SBUS, MODULE_TYPE_XJT_LITE_PXX2, - MODULE_TYPE_FLYSKY, + MODULE_TYPE_AFHDS3, //no more protocols possible because of 4 bits value MODULE_TYPE_COUNT, MODULE_TYPE_MAX = MODULE_TYPE_COUNT - 1 }; @@ -219,4 +219,13 @@ enum AntennaModes { ANTENNA_MODE_LAST = ANTENNA_MODE_EXTERNAL }; +enum AfhdsModes { + AFHDS_SUBTYPE_FIRST, + AFHDS_SUBTYPE_PWM_IBUS = AFHDS_SUBTYPE_FIRST, + AFHDS_SUBTYPE_PWM_SBUS, + AFHDS_SUBTYPE_PPM_IBUS, + AFHDS_SUBTYPE_PPM_SBUS, + AFHDS_SUBTYPE_LAST = AFHDS_SUBTYPE_PPM_SBUS +}; + #endif // _MODULES_CONSTANTS_H_ diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 24d065893..ee2b1157a 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -33,6 +33,7 @@ #endif #define CROSSFIRE_CHANNELS_COUNT 16 +#define GHOST_CHANNELS_COUNT 12 #if defined(MULTIMODULE) // When using packed, the pointer in here end up not being aligned, which clang and gcc complain about @@ -150,15 +151,15 @@ inline bool isModuleCrossfire(uint8_t idx) } #endif -#if defined(PCBFLYSKY) -inline bool isModuleFlysky(uint8_t idx) +#if defined(GHOST) +inline bool isModuleGhost(uint8_t idx) { - return g_model.moduleData[idx].type == MODULE_TYPE_FLYSKY; + return idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST; } #else -inline bool isModuleFlysky(uint8_t idx) +inline bool isModuleGhost(uint8_t idx) { - return idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_FLYSKY; + return false; } #endif @@ -190,7 +191,7 @@ inline bool isModulePPM(uint8_t moduleIdx) inline bool isModuleTypeR9MNonAccess(uint8_t type) { - return type == MODULE_TYPE_R9M_PXX1 || type == MODULE_TYPE_R9M_LITE_PXX1 || type == MODULE_TYPE_R9M_LITE_PRO_PXX1; + return type == MODULE_TYPE_R9M_PXX1 || type == MODULE_TYPE_R9M_LITE_PXX1; } inline bool isModuleR9MNonAccess(uint8_t idx) @@ -230,7 +231,7 @@ inline bool isModuleR9MLiteNonPro(uint8_t idx) inline bool isModuleTypeR9MLitePro(uint8_t type) { - return type == MODULE_TYPE_R9M_LITE_PRO_PXX1 || type == MODULE_TYPE_R9M_LITE_PRO_PXX2; + return type == MODULE_TYPE_R9M_LITE_PRO_PXX2; } inline bool isModuleTypeR9MLite(uint8_t type) @@ -311,8 +312,14 @@ inline bool isModuleSBUS(uint8_t moduleIdx) return g_model.moduleData[moduleIdx].type == MODULE_TYPE_SBUS; } +inline bool isModuleAFHDS3(uint8_t idx) +{ + return g_model.moduleData[idx].type == MODULE_TYPE_AFHDS3; +} + // order is the same as in enum Protocols in myeeprom.h (none, ppm, pxx, pxx2, dsm, crossfire, multi, r9m, r9m2, sbus) -static const int8_t maxChannelsModules_M8[] = { 0, 8, 8, 16, -2, 8, 4, 8, 16, 8}; // relative to 8! +//qba667 count is not matching! +static const int8_t maxChannelsModules_M8[] = { 0, 8, 8, 16, -2, 8, 4, 8, 16, 8, 10 }; // relative to 8! static const int8_t maxChannelsXJT_M8[] = { 0, 8, 0, 4 }; // relative to 8! constexpr int8_t MAX_TRAINER_CHANNELS_M8 = MAX_TRAINER_CHANNELS - 8; @@ -337,6 +344,9 @@ inline int8_t maxModuleChannels_M8(uint8_t moduleIdx) return 8; // always 16 channels in FCC / FLEX } } + else if (isModuleAFHDS3(moduleIdx)) { + return 10; + } else { return maxChannelsModules_M8[g_model.moduleData[moduleIdx].type]; } @@ -369,8 +379,6 @@ inline int8_t defaultModuleChannels_M8(uint8_t idx) return 4; // 12 channels else if (isModulePXX2(idx)) return 8; // 16 channels - else if (isModuleFlysky(idx)) - return 6; // 14 channels else return maxModuleChannels_M8(idx); } @@ -384,6 +392,8 @@ inline int8_t sentModuleChannels(uint8_t idx) { if (isModuleCrossfire(idx)) return CROSSFIRE_CHANNELS_COUNT; + else if (isModuleGhost(idx)) + return GHOST_CHANNELS_COUNT; else if (isModuleMultimodule(idx) && !isModuleMultimoduleDSM2(idx)) return 16; else if (isModuleSBUS(idx)) @@ -414,7 +424,7 @@ inline bool isModuleRxNumAvailable(uint8_t moduleIdx) if (isModuleMultimodule(moduleIdx)) return true; - if(isModuleMultimodule(moduleIdx)) + if (isModuleCrossfire(moduleIdx)) return true; return false; @@ -454,7 +464,7 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx) return g_model.moduleData[moduleIdx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16; #if defined(MULTIMODULE) - if (isModuleMultimodule(moduleIdx)){ + if (isModuleMultimodule(moduleIdx)) { MultiModuleStatus &status = getMultiModuleStatus(moduleIdx); if (status.isValid()) { return status.supportsFailsafe(); @@ -466,6 +476,11 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx) } #endif +#if defined(AFHDS3) + if (isModuleAFHDS3(moduleIdx)) + return true; +#endif + if (isModuleR9M(moduleIdx)) return true; @@ -474,7 +489,7 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx) inline bool isModuleBindRangeAvailable(uint8_t moduleIdx) { - return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx); + return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx) || isModuleAFHDS3(moduleIdx); } inline bool isModuleRangeAvailable(uint8_t moduleIdx) @@ -549,7 +564,7 @@ inline bool isTelemAllowedOnBind(uint8_t moduleIndex) return true; } - if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M_PXX1 || g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M_LITE_PRO_PXX1) { + if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M_PXX1) { if (isModuleR9M_LBT(EXTERNAL_MODULE)) return g_model.moduleData[EXTERNAL_MODULE].pxx.power < R9M_LBT_POWER_200_16CH_NOTELEM; else @@ -601,6 +616,30 @@ inline void resetAccessAuthenticationCount() #endif } +inline void resetAfhds3Options(uint8_t moduleIdx) +{ + auto & data = g_model.moduleData[moduleIdx]; + data.rfProtocol = 0; + data.subType = 0; +#if defined(AFHDS3) + data.afhds3.bindPower = 0; + data.afhds3.runPower = 0; + data.afhds3.emi = 0; + data.afhds3.telemetry = 1; + data.afhds3.rx_freq[0] = 50; + data.afhds3.rx_freq[1] = 0; + data.afhds3.failsafeTimeout = 1000; + data.channelsCount = 14 - 8; + data.failsafeMode = 1; + //" PWM+i"" PWM+s"" PPM+i"" PPM+s" + data.subType = 0; + for (uint8_t channel = 0; channel < MAX_OUTPUT_CHANNELS; channel++) { + g_model.failsafeChannels[channel] = 0; + } +#endif +} + + inline void setModuleType(uint8_t moduleIdx, uint8_t moduleType) { ModuleData & moduleData = g_model.moduleData[moduleIdx]; @@ -611,6 +650,8 @@ inline void setModuleType(uint8_t moduleIdx, uint8_t moduleType) moduleData.sbus.refreshRate = -31; else if (moduleData.type == MODULE_TYPE_PPM) setDefaultPpmFrameLength(moduleIdx); + else if (moduleData.type == MODULE_TYPE_AFHDS3) + resetAfhds3Options(moduleIdx); else resetAccessAuthenticationCount(); } @@ -662,6 +703,10 @@ inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max) min = -1; max = 84; break; + case MODULE_SUBTYPE_MULTI_FRSKY_R9: + min = 0; // 10mW + max = 5; // 300mW + break; default: min = -128; max = 127; diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index cfcff15d0..dcc7c7f9c 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -42,6 +42,7 @@ static void sendD16BindOption(uint8_t moduleIdx); #if defined(LUA) static void sendSport(uint8_t moduleIdx); static void sendHott(uint8_t moduleIdx); +static void sendDSM(uint8_t moduleIdx); #endif void multiPatchCustom(uint8_t moduleIdx) @@ -167,18 +168,23 @@ void setupPulsesMulti(uint8_t moduleIdx) sendChannels(moduleIdx); // Multi V1.3.X.X -> Send byte 26, Protocol (bits 7 & 6), RX_Num (bits 5 & 4), invert, not used, disable telemetry, disable mapping - sendMulti(moduleIdx, (uint8_t) (((g_model.moduleData[moduleIdx].getMultiProtocol()+3)&0xC0) - | (g_model.header.modelId[moduleIdx] & 0x30) - | (invert[moduleIdx] & 0x08) - //| 0x04 // Future use - | (g_model.moduleData[moduleIdx].multi.disableTelemetry << 1) - | g_model.moduleData[moduleIdx].multi.disableMapping)); - + if (moduleState[moduleIdx].mode == MODULE_MODE_SPECTRUM_ANALYSER) { + sendMulti(moduleIdx, invert[moduleIdx] & 0x08); + } + else { + sendMulti(moduleIdx, (uint8_t) (((g_model.moduleData[moduleIdx].getMultiProtocol() + 3) & 0xC0) + | (g_model.header.modelId[moduleIdx] & 0x30) + | (invert[moduleIdx] & 0x08) + //| 0x04 // Future use + | (g_model.moduleData[moduleIdx].multi.disableTelemetry << 1) + | g_model.moduleData[moduleIdx].multi.disableMapping)); + } + // Multi V1.3.X.X -> Send protocol additional data: max 9 bytes if (getMultiModuleStatus(moduleIdx).isValid()) { MultiModuleStatus &status = getMultiModuleStatus(moduleIdx); if (status.minor >= 3 && !(status.flags & 0x80)) { //Version 1.3.x.x or more and Buffer not full - if (IS_D16_MULTI(moduleIdx) && moduleState[moduleIdx].mode == MODULE_MODE_BIND) { + if ((IS_D16_MULTI(moduleIdx) || IS_R9_MULTI(moduleIdx)) && moduleState[moduleIdx].mode == MODULE_MODE_BIND) { sendD16BindOption(moduleIdx);//1 byte of additional data } #if defined(LUA) @@ -189,6 +195,9 @@ void setupPulsesMulti(uint8_t moduleIdx) else if (IS_HOTT_MULTI(moduleIdx)) { sendHott(moduleIdx); //1 byte of additional data } + else if (IS_DSM_MULTI(moduleIdx)) { + sendDSM(moduleIdx); //7 bytes of additional data + } #endif } } @@ -313,15 +322,14 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe) // rfProtocol if (type == MODULE_SUBTYPE_MULTI_DSM2 +1 ) { - // Autobinding should always be done in DSMX 11ms - if (g_model.moduleData[moduleIdx].multi.autoBindMode && moduleState[moduleIdx].mode == MODULE_MODE_BIND) - subtype = MM_RF_DSM2_SUBTYPE_AUTO; - - // Multi module in DSM mode wants the number of channels to be used as option value - if (optionValue) - optionValue = 0x80 | sentModuleChannels(moduleIdx); // Max throw + // Multi module in DSM mode wants the number of channels to be used as option value along with other flags + if (optionValue & 0x01) + optionValue = 0x80; // Max throw else - optionValue = sentModuleChannels(moduleIdx); + optionValue = 0x00; + if (g_model.moduleData[moduleIdx].multi.optionValue & 0x02) + optionValue |= 0x40; // 11ms servo refresh + optionValue |= sentModuleChannels(moduleIdx); //add number of channels } // Special treatment for the FrSky entry... @@ -336,7 +344,6 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe) if (g_model.moduleData[moduleIdx].getMultiProtocol() == MM_RF_CUSTOM_SELECTED) type = g_model.moduleData[moduleIdx].getMultiProtocol(); - uint8_t headerByte = 0x55; // header, byte 0, 0x55 for proto 0-31, 0x54 for proto 32-63 if (type & 0x20) @@ -398,4 +405,18 @@ void sendHott(uint8_t moduleIdx) sendMulti(moduleIdx, Multi_Buffer[5]); } } + +void sendDSM(uint8_t moduleIdx) +{ + // 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 + if (Multi_Buffer && memcmp(Multi_Buffer, "DSM", 3) == 0 && (Multi_Buffer[3] & 0xF8) == 0x70) { + for(uint8_t i = 0; i < 7; i++) { + sendMulti(moduleIdx, Multi_Buffer[3+i]); + } + Multi_Buffer[3] = 0x00; // Data sent + } +} #endif diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index f0e48f4b6..d6833bfe9 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -28,6 +28,7 @@ InternalModulePulsesData intmodulePulsesData __DMA; ExternalModulePulsesData extmodulePulsesData __DMA; TrainerPulsesData trainerPulsesData __DMA; +//use only for PXX void ModuleState::startBind(BindInformation * destination, ModuleCallback bindCallback) { bindInformation = destination; @@ -40,6 +41,56 @@ void ModuleState::startBind(BindInformation * destination, ModuleCallback bindCa #endif } +void getModuleStatusString(uint8_t moduleIdx, char * statusText) +{ + *statusText = 0; +#if defined(MULTIMODULE) + if (isModuleMultimodule(moduleIdx)) { + //change it + getMultiModuleStatus(moduleIdx).getStatusString(statusText); + } +#endif +#if defined(AFHDS3) + if (moduleIdx == EXTERNAL_MODULE && isModuleAFHDS3(moduleIdx)) { + extmodulePulsesData.afhds3.getStatusString(statusText); + } +#endif +} + +void getModuleSyncStatusString(uint8_t moduleIdx, char * statusText) +{ + *statusText = 0; +#if defined(MULTIMODULE) + if (isModuleMultimodule(moduleIdx)) { + getMultiSyncStatus(moduleIdx).getRefreshString(statusText); + } +#endif +#if defined(AFHDS3) + if (moduleIdx == EXTERNAL_MODULE && isModuleAFHDS3(moduleIdx)) { + extmodulePulsesData.afhds3.getPowerStatus(statusText); + } +#endif +} + +#if defined(AFHDS3) +uint8_t actualAfhdsRunPower(int moduleIndex) +{ + if (moduleIndex == EXTERNAL_MODULE && isModuleAFHDS3(moduleIndex)) { + return (uint8_t)extmodulePulsesData.afhds3.actualRunPower(); + } + return 0; +} +#endif + +ModuleSettingsMode getModuleMode(int moduleIndex) +{ + return (ModuleSettingsMode)moduleState[moduleIndex].mode; +} +void setModuleMode(int moduleIndex, ModuleSettingsMode mode) +{ + moduleState[moduleIndex].mode = mode; +} + uint8_t getModuleType(uint8_t module) { uint8_t type = g_model.moduleData[module].type; @@ -82,7 +133,6 @@ uint8_t getRequiredProtocol(uint8_t module) #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) case MODULE_TYPE_R9M_LITE_PXX1: - case MODULE_TYPE_R9M_LITE_PRO_PXX1: protocol = PROTOCOL_CHANNELS_PXX1_SERIAL; break; @@ -136,6 +186,18 @@ uint8_t getRequiredProtocol(uint8_t module) break; #endif +#if defined(AFHDS3) + case MODULE_TYPE_AFHDS3: + protocol = PROTOCOL_CHANNELS_AFHDS3; + break; +#endif + +#if defined(GHOST) + case MODULE_TYPE_GHOST: + protocol = PROTOCOL_CHANNELS_GHOST; + break; +#endif + default: protocol = PROTOCOL_CHANNELS_NONE; break; @@ -186,6 +248,12 @@ void enablePulsesExternalModule(uint8_t protocol) break; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + EXTERNAL_MODULE_ON(); + break; +#endif + #if defined(PXX2) && defined(EXTMODULE_USART) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: extmoduleInvertedSerialStart(PXX2_HIGHSPEED_BAUDRATE); @@ -214,6 +282,14 @@ void enablePulsesExternalModule(uint8_t protocol) break; #endif +#if defined(AFHDS3) + case PROTOCOL_CHANNELS_AFHDS3: + extmodulePulsesData.afhds3.init(EXTERNAL_MODULE); + extmoduleSerialStart(AFHDS3_BAUDRATE, AFHDS3_COMMAND_TIMEOUT * 2000, false); + break; +#endif + + default: break; } @@ -267,6 +343,13 @@ bool setupPulsesExternalModule(uint8_t protocol) return true; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + setupPulsesGhost(); + scheduleNextMixerCalculation(EXTERNAL_MODULE, GHOST_PERIOD); + return true; +#endif + #if defined(MULTIMODULE) case PROTOCOL_CHANNELS_MULTIMODULE: setupPulsesMultiExternalModule(); @@ -281,6 +364,13 @@ bool setupPulsesExternalModule(uint8_t protocol) return true; #endif +#if defined(AFHDS3) + case PROTOCOL_CHANNELS_AFHDS3: + extmodulePulsesData.afhds3.setupFrame(); + scheduleNextMixerCalculation(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT); + return true; +#endif + default: scheduleNextMixerCalculation(EXTERNAL_MODULE, 50/*ms*/); return false; @@ -438,3 +528,8 @@ void setCustomFailsafe(uint8_t moduleIndex) } } } + +int32_t getChannelValue(uint8_t channel) { + return channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; +} + diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index e2db4783e..d877accea 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -27,7 +27,7 @@ #include "pxx1.h" #include "pxx2.h" #include "multi.h" -#include "flysky.h" +#include "afhds3.h" #include "modules_helpers.h" #include "ff.h" @@ -36,12 +36,6 @@ extern uint8_t dsm2BindTimer; #endif -#if defined(PCBFLYSKY) - #define IS_FLYSKY_PROTOCOL(protocol) (protocol==PROTO_FLYSKY) -#else - #define IS_FLYSKY_PROTOCOL(protocol) (0) -#endif - #if defined(DSM2) #define IS_DSM2_PROTOCOL(protocol) (protocol>=PROTOCOL_CHANNELS_DSM2_LP45 && protocol<=PROTOCOL_CHANNELS_DSM2_DSMX) #else @@ -63,29 +57,14 @@ #define IS_MULTIMODULE_PROTOCOL(protocol) (0) #endif -#define IS_SBUS_PROTOCOL(protocol) (protocol == PROTOCOL_CHANNELS_SBUS) +#if defined(AFHDS3) +#define IS_AFHDS3_PROTOCOL(protocol) (protocol == PROTOCOL_CHANNELS_AFHDS3) +#else +#define IS_AFHDS3_PROTOCOL(protocol) (0) +#endif extern uint8_t s_pulses_paused; -enum ModuleSettingsMode -{ - MODULE_MODE_NORMAL, - MODULE_MODE_SPECTRUM_ANALYSER, - MODULE_MODE_POWER_METER, - MODULE_MODE_GET_HARDWARE_INFO, - MODULE_MODE_MODULE_SETTINGS, - MODULE_MODE_RECEIVER_SETTINGS, - MODULE_MODE_BEEP_FIRST, - MODULE_MODE_REGISTER = MODULE_MODE_BEEP_FIRST, - MODULE_MODE_BIND, - MODULE_MODE_SHARE, - MODULE_MODE_RANGECHECK, - MODULE_MODE_RESET, - MODULE_MODE_AUTHENTICATION, - MODULE_MODE_OTA_UPDATE, -}; - - PACK(struct PXX2Version { uint8_t major; uint8_t revision:4; @@ -132,6 +111,7 @@ class ReceiverSettings { uint8_t pwmRate; uint8_t fport; uint8_t enablePwmCh5Ch6; + uint8_t fport2; uint8_t outputsCount; uint8_t outputsMapping[24]; }; @@ -268,6 +248,12 @@ PACK(struct CrossfirePulsesData { uint8_t length; }); +#define GHOST_FRAME_MAXLEN 16 +PACK(struct GhostPulsesData { + uint8_t pulses[GHOST_FRAME_MAXLEN]; + uint8_t length; +}); + union InternalModulePulsesData { #if defined(PXX1) #if defined(INTMODULE_USART) @@ -276,9 +262,7 @@ union InternalModulePulsesData { PwmPxx1Pulses pxx; #endif #endif -#if defined(AFHDS2) - FlySkySerialPulsesData flysky; -#endif + #if defined(PXX2) Pxx2Pulses pxx2; #endif @@ -311,13 +295,16 @@ union ExternalModulePulsesData { #if defined(DSM2) || defined(MULTIMODULE) || defined(SBUS) Dsm2PulsesData dsm2; #endif + #if defined(AFHDS3) - FlySkySerialPulsesData flysky; + afhds3::PulsesData afhds3; #endif PpmPulsesData ppm; CrossfirePulsesData crossfire; + + GhostPulsesData ghost; } __ALIGNED(4); /* The __ALIGNED keyword is required to align the struct inside the modulePulsesData below, @@ -342,6 +329,7 @@ bool setupPulsesInternalModule(); bool setupPulsesExternalModule(); void setupPulsesDSM2(); void setupPulsesCrossfire(); +void setupPulsesGhost(); void setupPulsesMultiExternalModule(); void setupPulsesMultiInternalModule(); void setupPulsesSbus(); @@ -360,6 +348,11 @@ void extmodulePxx1SerialStart(); void extmodulePpmStart(); void intmoduleStop(); void extmoduleStop(); +void getModuleStatusString(uint8_t moduleIdx, char * statusText); +void getModuleSyncStatusString(uint8_t moduleIdx, char * statusText); +#if defined(AFHDS3) +uint8_t actualAfhdsRunPower(int moduleIndex); +#endif void extramodulePpmStart(); inline void startPulses() @@ -391,7 +384,8 @@ enum ChannelsProtocols { PROTOCOL_CHANNELS_SBUS, PROTOCOL_CHANNELS_PXX2_LOWSPEED, PROTOCOL_CHANNELS_PXX2_HIGHSPEED, - PROTOCOL_CHANNELS_FLYSKY + PROTOCOL_CHANNELS_AFHDS3, + PROTOCOL_CHANNELS_GHOST }; inline void stopPulses() @@ -457,4 +451,4 @@ inline bool isModuleInBeepMode() return false; } -#endif // _PULSES_H_ \ No newline at end of file +#endif // _PULSES_H_ diff --git a/radio/src/pulses/pulses_common.h b/radio/src/pulses/pulses_common.h index 83058f635..80f5518a1 100644 --- a/radio/src/pulses/pulses_common.h +++ b/radio/src/pulses/pulses_common.h @@ -31,6 +31,27 @@ typedef uint16_t trainer_pulse_duration_t; +enum ModuleSettingsMode +{ + MODULE_MODE_NORMAL, + MODULE_MODE_SPECTRUM_ANALYSER, + MODULE_MODE_POWER_METER, + MODULE_MODE_GET_HARDWARE_INFO, + MODULE_MODE_MODULE_SETTINGS, + MODULE_MODE_RECEIVER_SETTINGS, + MODULE_MODE_BEEP_FIRST, + MODULE_MODE_REGISTER = MODULE_MODE_BEEP_FIRST, + MODULE_MODE_BIND, + MODULE_MODE_SHARE, + MODULE_MODE_RANGECHECK, + MODULE_MODE_RESET, + MODULE_MODE_AUTHENTICATION, + MODULE_MODE_OTA_UPDATE, +}; + +ModuleSettingsMode getModuleMode(int moduleIndex); +void setModuleMode(int moduleIndex, ModuleSettingsMode mode); + template class DataBuffer { public: diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp index 4dfa3be95..ba05d026e 100644 --- a/radio/src/pulses/pxx1.cpp +++ b/radio/src/pulses/pxx1.cpp @@ -208,7 +208,7 @@ void Pxx1Pulses::setupFrame(uint8_t module) add8ChannelsFrame(module, sendUpperChannels, sendFailsafe); if (moduleState[module].counter-- == 0) { - moduleState[module].counter = 1000; + moduleState[module].counter = 999; } } diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index 2724def67..5f53a446e 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -228,6 +228,8 @@ void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module) flag1 |= PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW; if (reusableBuffer.hardwareAndSettings.receiverSettings.enablePwmCh5Ch6) flag1 |= PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6; + if (reusableBuffer.hardwareAndSettings.receiverSettings.fport2) + flag1 |= PXX2_RX_SETTINGS_FLAG1_FPORT2; Pxx2Transport::addByte(flag1); uint8_t outputsCount = min(24, reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount); for (int i = 0; i < outputsCount; i++) { diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index 9655ac521..9fe910c5c 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -56,6 +56,7 @@ #define PXX2_RX_SETTINGS_FLAG1_FPORT (1 << 3) #define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW (1 << 2) #define PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6 (1 << 1) +#define PXX2_RX_SETTINGS_FLAG1_FPORT2 (1 << 0) #define PXX2_TX_SETTINGS_FLAG0_WRITE (1 << 6) #define PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA (1 << 3) @@ -221,16 +222,16 @@ static const uint8_t PXX2ReceiverOptions[] = { 0b11111110, // X8R 0b11111110, // RX8R 0b11111110, // RX8R-PRO - 0b11111110, // RX6R - 0b11111110, // RX4R - 0b11111110, // G-RX8 - 0b11111110, // G-RX6 + 0b11111111, // RX6R + 0b11111111, // RX4R + 0b11111111, // G-RX8 + 0b11111111, // G-RX6 0b11111110, // X6R 0b11111110, // X4R 0b11111110, // X4R-SB 0b11111110, // XSR 0b11111110, // XSR-M - 0b11111110, // RXSR + 0b11111111, // RXSR 0b11111110, // S6R 0b11111110, // S8R 0b11111110, // XM @@ -267,6 +268,7 @@ enum ReceiverCapabilities { RECEIVER_CAPABILITY_FPORT, RECEIVER_CAPABILITY_TELEMETRY_25MW, RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6, + RECEIVER_CAPABILITY_FPORT2, RECEIVER_CAPABILITY_COUNT }; diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index bb0498d6f..6f390068e 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -130,6 +130,8 @@ const char * getBasename(const char * path); #define OTX_FOURCC 0x3478746F // otx for X12S #elif defined(RADIO_T16) #define OTX_FOURCC 0x3F78746F // otx for Jumper T16 +#elif defined(RADIO_T18) + #define OTX_FOURCC 0x4078746F // otx for Jumper T18 #elif defined(RADIO_TX16S) #define OTX_FOURCC 0x3878746F // otx for Radiomaster TX16S #elif defined(PCBX10) diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index 915fb7afb..8a83d586a 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -36,11 +36,14 @@ #define DISPLAY_VERSION "-radiomaster" #elif defined(TBS_RELEASE) #define DISPLAY_VERSION "-tbs" +#elif defined(IMRC_RELEASE) +#define DISPLAY_VERSION "-imrc" #else #define DISPLAY_VERSION #endif #if defined(COLORLCD) + const char fw_stamp[] = "FW" TAB ": opentx-" FLAVOUR; const char vers_stamp[] = "VERS" TAB ": " VERSION DISPLAY_VERSION " (" GIT_STR ")"; const char date_stamp[] = "DATE" TAB ": " DATE; const char time_stamp[] = "TIME" TAB ": " TIME; diff --git a/radio/src/storage/modelslist.cpp b/radio/src/storage/modelslist.cpp index 892542b64..54762d76a 100644 --- a/radio/src/storage/modelslist.cpp +++ b/radio/src/storage/modelslist.cpp @@ -149,7 +149,7 @@ void ModelCell::setModelId(uint8_t moduleIdx, uint8_t id) // getTimerString(timer, 0); // for (uint8_t i = 0; i < MAX_TIMERS; i++) { // if (partialmodel.timers[i].mode != 0 && partialmodel.timers[i].persistent) { -// getTimerString(timer, partialmodel.timers[i].value); +// getTimerString(timer, partialmodel.timers[i].value, 1); // break; // } // } diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 5e7c1e39f..8ef8f8d2b 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -159,7 +159,11 @@ char * strAppendStringWithIndex(char * dest, const char * s, int idx) return strAppendUnsigned(strAppend(dest, s), abs(idx)); } -char * getTimerString(char * dest, int32_t tme, uint8_t hours) +constexpr int secondsPerDay = 24 * 3600; +constexpr int secondsPer99Hours = 99*3600 + 59*60 + 59; +constexpr int secondsPerYear = 365 * secondsPerDay; + +char * getTimerString(char * dest, int tme, uint8_t hours) { char * s = dest; div_t qr; @@ -169,28 +173,63 @@ char * getTimerString(char * dest, int32_t tme, uint8_t hours) *s++ = '-'; } - qr = div((int)tme, 60); + if (tme < secondsPerDay) { + qr = div((int) tme, 60); - if (hours) { - div_t qr2 = div(qr.quot, 60); + if (hours) { + div_t qr2 = div(qr.quot, 60); + *s++ = '0' + (qr2.quot / 10); + *s++ = '0' + (qr2.quot % 10); + *s++ = ':'; + qr.quot = qr2.rem; + } + + if (!hours && qr.quot > 99) { + *s++ = '0' + (qr.quot / 100); + qr.quot = qr.quot % 100; + } + + *s++ = '0' + (qr.quot / 10); + *s++ = '0' + (qr.quot % 10); + *s++ = ':'; + *s++ = '0' + (qr.rem / 10); + *s++ = '0' + (qr.rem % 10); + *s = '\0'; + } + else if (tme < secondsPer99Hours) { + qr = div(tme, 3600); + div_t qr2 = div(qr.rem, 60); + *s++ = '0' + (qr.quot / 10); + *s++ = '0' + (qr.quot % 10); + *s++ = 'H'; *s++ = '0' + (qr2.quot / 10); *s++ = '0' + (qr2.quot % 10); - *s++ = ':'; - qr.quot = qr2.rem; + *s = '\0'; } - - if (!hours && qr.quot > 99) { + else if (tme < secondsPerYear) { + qr = div(tme, secondsPerDay); + div_t qr2 = div(qr.rem, 60); *s++ = '0' + (qr.quot / 100); - qr.quot = qr.quot % 100; + *s++ = '0' + (qr.quot / 10); + *s++ = '0' + (qr.quot % 10); + *s++ = 'D'; + *s++ = '0' + (qr2.quot / 10); + *s++ = '0' + (qr2.quot % 10); + *s++ = 'H'; + *s = '\0'; + } + else { + qr = div(tme, secondsPerYear); + div_t qr2 = div(qr.rem, secondsPerDay); + *s++ = '0' + (qr.quot / 10); + *s++ = '0' + (qr.quot % 10); + *s++ = 'Y'; + *s++ = 'Y'; + *s++ = '0' + (qr2.quot / 10); + *s++ = '0' + (qr2.quot % 10); + *s++ = 'D'; + *s = '\0'; } - - *s++ = '0' + (qr.quot / 10); - *s++ = '0' + (qr.quot % 10); - *s++ = ':'; - *s++ = '0' + (qr.rem / 10); - *s++ = '0' + (qr.rem % 10); - *s = '\0'; - return dest; } diff --git a/radio/src/strhelpers.h b/radio/src/strhelpers.h index 3cdd33a86..54481a75f 100644 --- a/radio/src/strhelpers.h +++ b/radio/src/strhelpers.h @@ -34,7 +34,7 @@ char * strAppendFilename(char * dest, const char * filename, const int size); char * getStringAtIndex(char * dest, const char * s, int idx); char * strAppendStringWithIndex(char * dest, const char * s, int idx); #define LEN_TIMER_STRING 10 // "-00:00:00" -char * getTimerString(char * dest, int32_t tme, uint8_t hours=0); +char * getTimerString(char * dest, int tme, uint8_t hours=0); char * getCurveString(char * dest, int idx); char * getGVarString(char * dest, int idx); char * getGVarString(int idx); diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index e07dc1533..689d0ac51 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -180,6 +180,30 @@ if(CROSSFIRE) ) endif() +if(AFHDS3) + add_definitions(-DAFHDS3) + set(PULSES_SRC + ${PULSES_SRC} + afhds3.cpp + ) +endif() + +if(MULTIMODULE OR AFHDS3) + set(SRC ${SRC} telemetry/flysky_ibus.cpp ) +endif() + +if(GHOST) + add_definitions(-DGHOST) + set(PULSES_SRC + ${PULSES_SRC} + ghost.cpp + ) + set(SRC + ${SRC} + telemetry/ghost.cpp + ) +endif() + add_definitions(-g) add_definitions(-DCPUARM) @@ -254,11 +278,11 @@ if(SBUS) sbus.cpp ) endif() + if(AFHDS2) set(PULSES_SRC ${PULSES_SRC} afhds2.cpp - flysky.cpp ) endif() diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/adc_driver.cpp index 6360b9676..62eb5a7eb 100644 --- a/radio/src/targets/common/arm/stm32/adc_driver.cpp +++ b/radio/src/targets/common/arm/stm32/adc_driver.cpp @@ -24,6 +24,8 @@ // not needed #elif defined(RADIO_T16) const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; +#elif defined(RADIO_T18) + const int8_t adcDirection[NUM_ANALOGS] = { 1,-1,1,-1, -1,1,-1, -1,1, -1,1 }; #elif defined(RADIO_TX16S) const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; #elif defined(PCBX10) diff --git a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp index 9a066e1ad..eec3ffad3 100644 --- a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp @@ -21,6 +21,10 @@ #include "opentx.h" #include "targets/horus/board.h" +#if defined(SBUS) +extern Fifo trainerSbusFifo; +#endif + #if defined(AUX_SERIAL) uint8_t auxSerialMode = 0; Fifo auxSerialTxFifo; @@ -31,7 +35,7 @@ AuxSerialRxFifo auxSerialRxFifo __DMA (AUX_SERIAL_DMA_Stream_RX); AuxSerialRxFifo auxSerialRxFifo; #endif -void auxSerialSetup(unsigned int baudrate, bool dma) +void auxSerialSetup(unsigned int baudrate, bool dma, uint16_t lenght = USART_WordLength_8b, uint16_t parity = USART_Parity_No, uint16_t stop = USART_StopBits_1) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; @@ -54,9 +58,9 @@ void auxSerialSetup(unsigned int baudrate, bool dma) #endif USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_WordLength = lenght; + USART_InitStructure.USART_StopBits = stop; + USART_InitStructure.USART_Parity = parity; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(AUX_SERIAL_USART, &USART_InitStructure); @@ -123,11 +127,12 @@ void auxSerialInit(unsigned int mode, unsigned int protocol) #if defined(CROSSFIRE) if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) { auxSerialSetup(CROSSFIRE_TELEM_MIRROR_BAUDRATE, false); - AUX_SERIAL_POWER_OFF(); + AUX_SERIAL_POWER_ON(); break; } #endif auxSerialSetup(FRSKY_TELEM_MIRROR_BAUDRATE, false); + AUX_SERIAL_POWER_ON(); break; #if defined(DEBUG) || defined(CLI) @@ -140,10 +145,15 @@ void auxSerialInit(unsigned int mode, unsigned int protocol) case UART_MODE_TELEMETRY: if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) { auxSerialSetup(FRSKY_D_BAUDRATE, true); - AUX_SERIAL_POWER_OFF(); + AUX_SERIAL_POWER_ON(); } break; + case UART_MODE_SBUS_TRAINER: + auxSerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b + AUX_SERIAL_POWER_ON(); + break; + case UART_MODE_LUA: auxSerialSetup(DEBUG_BAUDRATE, false); AUX_SERIAL_POWER_ON(); @@ -165,9 +175,7 @@ void auxSerialPutc(char c) void auxSerialSbusInit() { - auxSerialSetup(SBUS_BAUDRATE, true); - AUX_SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ; - AUX_SERIAL_POWER_ON(); + auxSerialInit(UART_MODE_SBUS_TRAINER, 0); } void auxSerialStop() @@ -225,10 +233,15 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void) uint32_t status = AUX_SERIAL_USART->SR; while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { uint8_t data = AUX_SERIAL_USART->DR; + UNUSED(data); if (!(status & USART_FLAG_ERRORS)) { #if defined(LUA) & !defined(CLI) if (luaRxFifo && auxSerialMode == UART_MODE_LUA) luaRxFifo->push(data); +#endif +#if !defined(BOOT) + if (auxSerialMode == UART_MODE_SBUS_TRAINER) + trainerSbusFifo.push(data); #endif } status = AUX_SERIAL_USART->SR; @@ -241,7 +254,7 @@ uint8_t aux2SerialMode = 0; Fifo aux2SerialTxFifo; AuxSerialRxFifo aux2SerialRxFifo __DMA (AUX2_SERIAL_DMA_Stream_RX); -void aux2SerialSetup(unsigned int baudrate, bool dma) +void aux2SerialSetup(unsigned int baudrate, bool dma, uint16_t lenght = USART_WordLength_8b, uint16_t parity = USART_Parity_No, uint16_t stop = USART_StopBits_1) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; @@ -264,9 +277,9 @@ void aux2SerialSetup(unsigned int baudrate, bool dma) #endif USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_WordLength = lenght; + USART_InitStructure.USART_StopBits = stop; + USART_InitStructure.USART_Parity = parity; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(AUX2_SERIAL_USART, &USART_InitStructure); @@ -316,12 +329,12 @@ void aux2SerialInit(unsigned int mode, unsigned int protocol) #if defined(CROSSFIRE) if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) { aux2SerialSetup(CROSSFIRE_TELEM_MIRROR_BAUDRATE, false); - AUX2_SERIAL_POWER_OFF(); + AUX2_SERIAL_POWER_ON(); break; } #endif aux2SerialSetup(FRSKY_TELEM_MIRROR_BAUDRATE, false); - AUX2_SERIAL_POWER_OFF(); + AUX2_SERIAL_POWER_ON(); break; #if defined(DEBUG) || defined(CLI) @@ -334,10 +347,15 @@ void aux2SerialInit(unsigned int mode, unsigned int protocol) case UART_MODE_TELEMETRY: if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) { aux2SerialSetup(FRSKY_D_BAUDRATE, true); - AUX2_SERIAL_POWER_OFF(); + AUX2_SERIAL_POWER_ON(); } break; + case UART_MODE_SBUS_TRAINER: + aux2SerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b + AUX2_SERIAL_POWER_ON(); + break; + case UART_MODE_LUA: aux2SerialSetup(DEBUG_BAUDRATE, false); AUX2_SERIAL_POWER_ON(); @@ -359,9 +377,7 @@ void aux2SerialPutc(char c) void aux2SerialSbusInit() { - aux2SerialSetup(SBUS_BAUDRATE, true); - AUX2_SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ; - AUX2_SERIAL_POWER_ON(); + aux2SerialInit(UART_MODE_SBUS_TRAINER, 0); } void aux2SerialStop() @@ -416,10 +432,17 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void) uint32_t status = AUX2_SERIAL_USART->SR; while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { uint8_t data = AUX2_SERIAL_USART->DR; + UNUSED(data); if (!(status & USART_FLAG_ERRORS)) { -#if defined(LUA) - if (luaRxFifo && aux2SerialMode == UART_MODE_LUA) +#if defined(LUA) & !defined(CLI) + if (luaRxFifo && aux2SerialMode == UART_MODE_LUA) { luaRxFifo->push(data); + } +#endif +#if !defined(BOOT) + if (aux2SerialMode == UART_MODE_SBUS_TRAINER) { + trainerSbusFifo.push(data); + } #endif } status = AUX2_SERIAL_USART->SR; diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index 3492804f1..83a07d9d2 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -197,7 +197,8 @@ int main() RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | - AUX_SERIAL_RCC_AHB1Periph | AUX2_SERIAL_RCC_AHB1Periph | I2C_RCC_AHB1Periph | + AUX_SERIAL_RCC_AHB1Periph | AUX2_SERIAL_RCC_AHB1Periph | + I2C_RCC_AHB1Periph | KEYS_BACKLIGHT_RCC_AHB1Periph | SD_RCC_AHB1Periph, ENABLE); RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph | LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | diff --git a/radio/src/targets/common/arm/stm32/pwr_driver.cpp b/radio/src/targets/common/arm/stm32/pwr_driver.cpp index f488d19fa..220b5fdfd 100644 --- a/radio/src/targets/common/arm/stm32/pwr_driver.cpp +++ b/radio/src/targets/common/arm/stm32/pwr_driver.cpp @@ -51,6 +51,12 @@ void pwrInit() GPIO_InitStructure.GPIO_Pin = PWR_SWITCH_GPIO_PIN; GPIO_Init(PWR_SWITCH_GPIO, &GPIO_InitStructure); +#if defined(PWR_EXTRA_SWITCH_GPIO) + // PWR Extra switch + GPIO_InitStructure.GPIO_Pin = PWR_EXTRA_SWITCH_GPIO_PIN; + GPIO_Init(PWR_EXTRA_SWITCH_GPIO, &GPIO_InitStructure); +#endif + #if defined(PCBREV_HARDCODED) hardwareOptions.pcbrev = PCBREV_HARDCODED; #elif defined(PCBREV_GPIO_PIN) @@ -101,9 +107,20 @@ void pwrOff() GPIO_ResetBits(PWR_ON_GPIO, PWR_ON_GPIO_PIN); } +#if defined(PWR_EXTRA_SWITCH_GPIO) +bool pwrForcePressed() +{ + return (GPIO_ReadInputDataBit(PWR_SWITCH_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET && GPIO_ReadInputDataBit(PWR_EXTRA_SWITCH_GPIO, PWR_EXTRA_SWITCH_GPIO_PIN) == Bit_RESET); +} +#endif + bool pwrPressed() { +#if defined(PWR_EXTRA_SWITCH_GPIO) + return (GPIO_ReadInputDataBit(PWR_SWITCH_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET || GPIO_ReadInputDataBit(PWR_EXTRA_SWITCH_GPIO, PWR_EXTRA_SWITCH_GPIO_PIN) == Bit_RESET); +#else return GPIO_ReadInputDataBit(PWR_SWITCH_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET; +#endif } void pwrResetHandler() diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp index debe8793d..00b3c76f8 100644 --- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp +++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp @@ -71,7 +71,7 @@ void rotaryEncoderInit() void rotaryEncoderCheck() { -#if defined(RADIO_FAMILY_T16) +#if defined(RADIO_FAMILY_T16) && !defined(RADIO_T18) static uint8_t state = 0; uint8_t pins = ROTARY_ENCODER_POSITION(); diff --git a/radio/src/targets/common/arm/stm32/usb_driver.h b/radio/src/targets/common/arm/stm32/usb_driver.h index 90e1ccd84..350ceace0 100644 --- a/radio/src/targets/common/arm/stm32/usb_driver.h +++ b/radio/src/targets/common/arm/stm32/usb_driver.h @@ -21,6 +21,8 @@ #ifndef OPENTX_USB_DRIVER_H #define OPENTX_USB_DRIVER_H +#include + // USB driver enum usbMode { USB_UNSELECTED_MODE, diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 54d8f714b..39c63dee5 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -2,7 +2,9 @@ option(DISK_CACHE "Enable SD card disk cache" ON) option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON) option(PXX1 "PXX1 protocol support" ON) option(PXX2 "PXX2 protocol support" OFF) +option(AFHDS3 "AFHDS3 TX Module" ON) option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON) +option(GHOST "Ghost TX Module" ON) set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F4) @@ -62,6 +64,7 @@ if (PCB STREQUAL X10) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(BLUETOOTH ON) add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT) + add_definitions(-DRADIO_X10E) elseif (PCBREV STREQUAL T16) set(FLAVOUR t16) set(LUA_EXPORT lua_export_t16) @@ -80,11 +83,19 @@ if (PCB STREQUAL X10) set(HARDWARE_TOUCH YES) set(USB_CHARGER YES) set(DEFAULT_THEME "DARKBLUE") + set(SBUS_TRAINER ON) set(AUX_SERIAL OFF) # todo ON if (NOT BLUETOOTH AND NOT INTERNAL_GPS) set(AUX2_SERIAL OFF) # todo ON endif() set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") + elseif (PCBREV STREQUAL T18) + set(FLAVOUR t18) + set(LUA_EXPORT lua_export_t16) + add_definitions(-DRADIO_T18) + add_definitions(-DRADIO_FAMILY_T16) + option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" ON) + option(BLUETOOTH "Support for bluetooth module" OFF) else() set(FLAVOUR x10) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) @@ -216,6 +227,14 @@ if (AUX2_SERIAL) set(AUX_SERIAL_DRIVER ../common/arm/stm32/aux_serial_driver.cpp) endif() +if (SBUS_TRAINER) + add_definitions(-DSBUS_TRAINER) + set(SRC + ${SRC} + sbus.cpp + ) +endif() + set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} ${LCD_DRIVER} diff --git a/radio/src/targets/horus/backlight_driver.cpp b/radio/src/targets/horus/backlight_driver.cpp index e141cf5dd..13f73f1ee 100644 --- a/radio/src/targets/horus/backlight_driver.cpp +++ b/radio/src/targets/horus/backlight_driver.cpp @@ -32,6 +32,15 @@ void backlightInit() GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure); GPIO_PinAFConfig(BACKLIGHT_GPIO, BACKLIGHT_GPIO_PinSource, BACKLIGHT_GPIO_AF); +#if defined(KEYS_BACKLIGHT_GPIO) + GPIO_InitStructure.GPIO_Pin = KEYS_BACKLIGHT_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(KEYS_BACKLIGHT_GPIO, &GPIO_InitStructure); +#endif + // TIMER init #if defined(PCBX12S) && PCBREV >= 13 BACKLIGHT_TIMER->ARR = 100; @@ -72,6 +81,15 @@ void backlightEnable(uint8_t dutyCycle) BACKLIGHT_TIMER->CCR3 = BACKLIGHT_LEVEL_MAX - dutyCycle; #endif +#if defined(KEYS_BACKLIGHT_GPIO) && !defined(BOOT) + if (dutyCycle == 0 || g_eeGeneral.keysBacklight == 0) { + GPIO_ResetBits(KEYS_BACKLIGHT_GPIO, KEYS_BACKLIGHT_GPIO_PIN); + } + else { + GPIO_SetBits(KEYS_BACKLIGHT_GPIO, KEYS_BACKLIGHT_GPIO_PIN); + } +#endif + if (dutyCycle == 0) { BACKLIGHT_TIMER->BDTR &= ~TIM_BDTR_MOE; } diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index be11ea498..fb9da0d16 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -103,6 +103,7 @@ void boardInit() LED_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | + KEYS_BACKLIGHT_RCC_AHB1Periph | SD_RCC_AHB1Periph | AUDIO_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index c107d152d..3d8a9115c 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -93,6 +93,8 @@ enum { #elif defined(PCBX10) #if defined(PCBREV_EXPRESS) #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (hardwareOptions.pcbrev == PCBREV_X10_EXPRESS) + #elif defined(RADIO_FAMILY_T16) + #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (true) #else #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (hardwareOptions.pcbrev == PCBREV_X10_STD) #endif @@ -192,6 +194,9 @@ void stop_trainer_ppm(); void init_trainer_capture(); void stop_trainer_capture(); +// SBUS +int sbusGetByte(uint8_t * byte); + // Keys driver enum EnumKeys { @@ -381,7 +386,11 @@ enum Analogs { #define SLIDER2 SLIDER_FRONT_RIGHT #define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 14) + (SWITCH_3POS << 12) + (SWITCH_2POS << 10) + (SWITCH_3POS << 8) + (SWITCH_3POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0) -#define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 4) + (POT_MULTIPOS_SWITCH << 2) + (POT_WITHOUT_DETENT << 0) +#if defined(RADIO_FAMILY_T16) + #define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 4) + (POT_MULTIPOS_SWITCH << 2) + (POT_WITH_DETENT << 0) +#else + #define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 4) + (POT_MULTIPOS_SWITCH << 2) + (POT_WITHOUT_DETENT << 0) +#endif #if defined(PCBX12S) #define DEFAULT_SLIDERS_CONFIG (SLIDER_WITH_DETENT << 3) + (SLIDER_WITH_DETENT << 2) + (SLIDER_WITH_DETENT << 1) + (SLIDER_WITH_DETENT << 0) @@ -487,6 +496,11 @@ void pwrOn(); void pwrOff(); void pwrResetHandler(); bool pwrPressed(); +#if defined(PWR_EXTRA_SWITCH_GPIO) + bool pwrForcePressed(); +#else + #define pwrForcePressed() false +#endif uint32_t pwrPressedDuration(); // USB Charger @@ -535,7 +549,7 @@ void backlightEnable(uint8_t dutyCycle = 0); #else #define BACKLIGHT_LEVEL_MIN 46 #endif -#define BACKLIGHT_ENABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : BACKLIGHT_LEVEL_MAX - g_eeGeneral.backlightBright) +#define BACKLIGHT_ENABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : BACKLIGHT_LEVEL_MAX - currentBacklightBright) #define BACKLIGHT_DISABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : ((g_eeGeneral.blOffBright == BACKLIGHT_LEVEL_MIN) && (g_eeGeneral.backlightMode != e_backlight_mode_off)) ? 0 : g_eeGeneral.blOffBright) #define isBacklightEnabled() true @@ -550,6 +564,10 @@ void usbJoystickUpdate(); #define USB_NAME "Jumper T16" #define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */ #define USB_PRODUCT 'T', '1', '6', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ +#elif defined(RADIO_T18) + #define USB_NAME "Jumper T18" + #define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */ + #define USB_PRODUCT 'T', '1', '8', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ #elif defined(RADIO_TX16S) #define USB_NAME "RadioMas TX16S" #define USB_MANUFACTURER 'R', 'a', 'd', 'i', 'o', 'M', 'a', 's' /* 8 bytes */ diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 7e8b90937..47a40ae02 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -316,6 +316,30 @@ void extmoduleSendNextFrame() break; #endif +#if defined(AFHDS3) + case PROTOCOL_CHANNELS_AFHDS3: + { +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) + extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize()); +#else + const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData(); + uint32_t dataSize = extmodulePulsesData.afhds3.getSize(); + //Peripheral data size + //we know that afdhds3 uses 2 byte values! + uint32_t dmaSize = (EXTMODULE_TIMER_DMA_SIZE & (DMA_SxCR_PSIZE_0 | DMA_SxCR_PSIZE_1)) | DMA_SxCR_MSIZE_0; + + EXTMODULE_TIMER->CCR2 = dataPtr[dataSize -1] - 4000; // 2mS in advance + EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | dmaSize | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; + EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); + EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr); + EXTMODULE_TIMER_DMA_STREAM->NDTR = (uint32_t)dataSize; + EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA +#endif + } + break; +#endif + #if defined(DSM2) case PROTOCOL_CHANNELS_SBUS: #if defined(PCBX10) || PCBREV >= 13 @@ -344,6 +368,12 @@ void extmoduleSendNextFrame() break; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + sportSendBuffer(extmodulePulsesData.ghost.pulses, extmodulePulsesData.ghost.length); + break; +#endif + default: EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; break; diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index f4b49f5ae..6fe26dc00 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -324,7 +324,7 @@ #define ADC_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0) #if defined(RADIO_TX16S) #define ADC_VREF_PREC2 330 - #elif defined(RADIO_T16) + #elif defined(RADIO_T16) || defined(RADIO_T18) #define ADC_VREF_PREC2 300 #else #define ADC_VREF_PREC2 250 @@ -332,11 +332,21 @@ #endif // Power +#if defined(RADIO_T18) +#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOB +#define PWR_ON_GPIO GPIOJ +#define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01 +#define PWR_SWITCH_GPIO GPIOJ +#define PWR_SWITCH_GPIO_PIN GPIO_Pin_0 // PJ.00 +#define PWR_EXTRA_SWITCH_GPIO GPIOB +#define PWR_EXTRA_SWITCH_GPIO_PIN GPIO_Pin_0 // PB.00 +#else #define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ #define PWR_ON_GPIO GPIOJ #define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01 #define PWR_SWITCH_GPIO GPIOJ #define PWR_SWITCH_GPIO_PIN GPIO_Pin_0 // PJ.00 +#endif // USB Charger #if defined(USB_CHARGER) @@ -516,6 +526,9 @@ #define LCD_GPIO_NRST GPIOI #define LCD_GPIO_PIN_NRST GPIO_Pin_10 // PI.10 #endif +#if defined(PCBX10) && !defined(RADIO_T18) && !defined(SIMU) + #define LCD_VERTICAL_INVERT +#endif #if defined(PCBX10) && !defined(SIMU) #define LCD_VERTICAL_INVERT #endif @@ -554,6 +567,14 @@ #define BACKLIGHT_GPIO_AF GPIO_AF_TIM8 #define BACKLIGHT_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) #endif +#if defined(RADIO_T18) + #define KEYS_BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC + #define KEYS_BACKLIGHT_GPIO GPIOC + #define KEYS_BACKLIGHT_GPIO_PIN GPIO_Pin_4 // PC.04 + #define KEYS_BACKLIGHT_GPIO_PinSource GPIO_PinSource4 +#else + #define KEYS_BACKLIGHT_RCC_AHB1Periph 0 +#endif // SD #define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2) @@ -840,7 +861,7 @@ #define INTMODULE_HEARTBEAT #define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define INTMODULE_HEARTBEAT_GPIO GPIOD -#define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_12 +#define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_12 // PD.12 #define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOD #define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource12 #define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line12 diff --git a/radio/src/targets/horus/lcd_driver.cpp b/radio/src/targets/horus/lcd_driver.cpp index 265654e0e..08399cdf0 100644 --- a/radio/src/targets/horus/lcd_driver.cpp +++ b/radio/src/targets/horus/lcd_driver.cpp @@ -20,14 +20,25 @@ #include "opentx.h" -#define HBP 42 -#define VBP 12 +#if defined(RADIO_T18) + #define HBP 43 + #define VBP 12 -#define HSW 2 -#define VSW 10 + #define HSW 2 + #define VSW 4 -#define HFP 3 -#define VFP 2 + #define HFP 8 + #define VFP 8 +#else + #define HBP 42 + #define VBP 12 + + #define HSW 2 + #define VSW 10 + + #define HFP 3 + #define VFP 2 +#endif #define LCD_FIRST_LAYER 0 #define LCD_SECOND_LAYER 1 @@ -142,14 +153,18 @@ static void LCD_NRSTConfig(void) static void lcdReset() { - LCD_NRST_HIGH(); - delay_ms(1); +#if defined(RADIO_T18) // T18 screen has issues if NRST is ever brought low + NRST_HIGH(); +#else + NRST_HIGH(); + delay3(1); - LCD_NRST_LOW(); // RESET; - delay_ms(20); + NRST_LOW(); // RESET(); + delay3(20); - LCD_NRST_HIGH(); - delay_ms(20); + NRST_HIGH(); + delay3(30); +#endif } void LCD_Init_LTDC() diff --git a/radio/src/targets/horus/libopenui_config.h b/radio/src/targets/horus/libopenui_config.h index b41b1cee0..dd0fbbe72 100644 --- a/radio/src/targets/horus/libopenui_config.h +++ b/radio/src/targets/horus/libopenui_config.h @@ -170,7 +170,7 @@ constexpr LcdFlags MENU_FONT = FONT(STD); constexpr LcdFlags TABLE_HEADER_FONT = FONT(STD); constexpr LcdFlags TABLE_BODY_FONT = FONT(STD); -constexpr int CJK_FIRST_LETTER_INDEX = 168; +constexpr int CJK_FIRST_LETTER_INDEX = 189; constexpr coord_t CHAR_SPACING = 0; #endif // _LIBOPENUI_CONFIG_H_ diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index ffb1cbc2c..0288363be 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -45,7 +45,8 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) USART_DeInit(TELEMETRY_USART); return; } - + //deinit inverted mode + telemetryPortInvertedInit(0); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; @@ -136,6 +137,9 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) // soft serial vars static uint8_t rxBitCount; static uint8_t rxByte; +// single bit length expresses in half us +static uint16_t bitLength; +static uint16_t probeTimeFromStartBit; void telemetryPortInvertedInit(uint32_t baudrate) { @@ -155,6 +159,20 @@ void telemetryPortInvertedInit(uint32_t baudrate) rxBitCount = 0; + switch(baudrate) { + case 115200: + bitLength = 17; + probeTimeFromStartBit = 23; //because pin is not probed immediately + break; + case 57600: + bitLength = 35; //34 was used before - I prefer to use use 35 because of lower error + probeTimeFromStartBit = 48; // 48 used in original implementation + break; + default: + bitLength = 2000000/baudrate; //because of 0,5 us tick + probeTimeFromStartBit = 3000000/baudrate; + } + // configure bit sample timer TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS TELEMETRY_TIMER->CCER = 0; @@ -196,7 +214,7 @@ void telemetryPortInvertedRxBit() { if (rxBitCount < 8) { if (rxBitCount == 0) { - TELEMETRY_TIMER->ARR = 34; + TELEMETRY_TIMER->ARR = bitLength; rxByte = 0; } else { @@ -209,7 +227,6 @@ void telemetryPortInvertedRxBit() ++rxBitCount; } else if (rxBitCount == 8) { - telemetryNoDMAFifo.push(rxByte); rxBitCount = 0; @@ -223,6 +240,11 @@ void telemetryPortInvertedRxBit() void telemetryPortSetDirectionOutput() { +#if defined(GHOST) && SPORT_MAX_BAUDRATE < 400000 + if (isModuleGhost(EXTERNAL_MODULE)) { + TELEMETRY_USART->BRR = BRR_400K; + } +#endif TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver } @@ -235,6 +257,11 @@ void sportWaitTransmissionComplete() void telemetryPortSetDirectionInput() { sportWaitTransmissionComplete(); +#if defined(GHOST) && SPORT_MAX_BAUDRATE < 400000 + if (isModuleGhost(EXTERNAL_MODULE) && g_eeGeneral.telemetryBaudrate == GHST_TELEMETRY_RATE_115K) { + TELEMETRY_USART->BRR = BRR_115K; + } +#endif TELEMETRY_DIR_GPIO->BSRRH = TELEMETRY_DIR_GPIO_PIN; // output disable TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver } @@ -360,7 +387,7 @@ extern "C" void TELEMETRY_EXTI_IRQHandler(void) if (rxBitCount == 0) { - TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps + TELEMETRY_TIMER->ARR = probeTimeFromStartBit; // 1,5 cycle from start at 57600bps TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN; // disable start bit interrupt diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 4b4b50d37..931f60f21 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -20,6 +20,196 @@ #include "opentx.h" #include "tp_gt911.h" +#include "touch.h" + +//GT911 param table +const uint8_t TOUCH_GT911_Cfg[] = + { + GT911_CFG_NUMER, // 0x8047 Config version + 0xE0, // 0x8048 X output map : x 480 + 0x01, + 0x10, // 0x804A Y ouptut max : y 272 + 0x01, + GT911_MAX_TP, // 0x804C Touch number + 0x3C, // 0x804D Module switch 1 : bit4= xy change Int mode + 0x20, // 0x804E Module switch 2 + 0x22, // 0x804F Shake_Count + 0x0A, // 0x8050 Filter + 0x28, // 0x8051 Larger touch + 0x0F, // 0x8052 Noise reduction + 0x5A, // 0x8053 Screen touch level + 0x3C, // 0x8054 Screen touch leave + 0x03, // 0x8055 Low power control + 0x05, // 0x8056 Refresh rate + 0x00, // 0x8057 X threshold + 0x00, // 0x8058 Y threshold + 0x00, // 0x8059 Reserved + 0x00, // 0x805A Reserved + 0x11, // 0x805B Space (top, bottom) + 0x11, // 0x805C Space (left, right) + 0x08, // 0x805D Mini filter + 0x18, // 0x805E Strech R0 + 0x1A, // 0x805F Strech R1 + 0x1E, // 0x8060 Strech R2 + 0x14, // 0x8061 Strech RM + 0x87, // 0x8062 Drv groupA num + 0x29, // 0x8063 Drv groupB num + 0x0A, // 0x8064 Sensor num + 0xCF, // 0x8065 FreqA factor + 0xD1, // 0x8066 FreqB factor + 0xB2, // 0x8067 Panel bit freq + 0x04, + 0x00, // 0x8069 Reserved + 0x00, + 0x00, // 0x806B Panel tx gain + 0xD8, // 0x806C Panel rx gain + 0x02, // 0x806D Panel dump shift + 0x1D, // 0x806E Drv frame control + 0x00, // 0x806F Charging level up + 0x01, // 0x8070 Module switch 3 + 0x00, // 0x8071 Gesture distance + 0x00, // 0x8072 Gesture long press time + 0x00, // 0x8073 X/Y slope adjust + 0x00, // 0x8074 Gesture control + 0x00, // 0x8075 Gesture switch 1 + 0x00, // 0x8076 Gesture switch 2 + 0x00, // 0x8077 Gesture refresh rate + 0x00, // 0x8078 Gesture touch level + 0x00, // 0x8079 New green wake up level + 0xB4, // 0x807A Freq hopping start + 0xEF, // 0x807B Freq hopping end + 0x94, // 0x807C Noise detect time + 0xD5, // 0x807D Hopping flag + 0x02, // 0x807E Hopping flag + 0x07, // 0x807F Noise threshold + 0x00, // 0x8080 Nois min threshold old + 0x00, // 0x8081 Reserved + 0x04, // 0x8082 Hopping sensor group + 0x6E, // 0x8083 Hopping Seg1 normalize + 0xB9, // 0x8084 Hopping Seg1 factor + 0x00, // 0x8085 Main clock adjust + 0x6A, // 0x8086 Hopping Seg2 normalize + 0xC4, // 0x8087 Hopping Seg2 factor + 0x00, // 0x8088 Reserved + 0x66, // 0x8089 Hopping Seg3 normalize + 0xCF, // 0x808A Hopping Seg3 factor + 0x00, // 0x808B Reserved + 0x62, // 0x808C Hopping Seg4 normalize + 0xDB, // 0x808D Hopping Seg4 factor + 0x00, // 0x808E Reserved + 0x5E, // 0x808F Hopping Seg5 normalize + 0xE8, // 0x8090 Hopping Seg5 factor + 0x00, // 0x8091 Reserved + 0x5E, // 0x8092 Hopping Seg6 normalize + 0x00, // 0x8093 Key1 + 0x00, // 0x8094 Key2 + 0x00, // 0x8095 Key3 + 0x00, // 0x8096 Key4 + 0x00, // 0x8097 Key area + 0x00, // 0x8098 Key touch level + 0x00, // 0x8099 Key leave level + 0x00, // 0x809A Key sens + 0x00, // 0x809B Key sens + 0x00, // 0x809C Key restrain + 0x00, // 0x809D Key restrain time + 0x00, // 0x809E Large gesture touch + 0x00, // 0x809F Reserved + 0x00, // 0x80A0 Reserved + 0x00, // 0x80A1 Hotknot noise map + 0x00, // 0x80A2 Link threshold + 0x00, // 0x80A3 Pxy threshold + 0x00, // 0x80A4 GHot dump shift + 0x00, // 0x80A5 GHot rx gain + 0x00, // 0x80A6 Freg gain + 0x00, // 0x80A7 Freg gain 1 + 0x00, // 0x80A8 Freg gain 2 + 0x00, // 0x80A9 Freg gain 3 + 0x00, // 0x80AA Reserved + 0x00, // 0x80AB Reserved + 0x00, // 0x80AC Reserved + 0x00, // 0x80AD Reserved + 0x00, // 0x80AE Reserved + 0x00, // 0x80AF Reserved + 0x00, // 0x80B0 Reserved + 0x00, // 0x80B1 Reserved + 0x00, // 0x80B2 Reserved + 0x00, // 0x80B3 Combine dis + 0x00, // 0x80B4 Split set + 0x00, // 0x80B5 Reserved + 0x00, // 0x80B6 Reserved + 0x14, // 0x80B7 Sensor CH0 + 0x12, // 0x80B8 Sensor CH1 + 0x10, // 0x80B9 Sensor CH2 + 0x0E, // 0x80BA Sensor CH3 + 0x0C, // 0x80BB Sensor CH4 + 0x0A, // 0x80BC Sensor CH5 + 0x08, // 0x80BD Sensor CH6 + 0x06, // 0x80BE Sensor CH7 + 0x04, // 0x80BF Sensor CH8 + 0x02, // 0x80C0 Sensor CH9 + 0xFF, // 0x80C1 Sensor CH10 + 0xFF, // 0x80C2 Sensor CH11 + 0xFF, // 0x80C3 Sensor CH12 + 0xFF, // 0x80C4 Sensor CH13 + 0x00, // 0x80C5 Reserved + 0x00, // 0x80C6 Reserved + 0x00, // 0x80C7 Reserved + 0x00, // 0x80C8 Reserved + 0x00, // 0x80C9 Reserved + 0x00, // 0x80CA Reserved + 0x00, // 0x80CB Reserved + 0x00, // 0x80CC Reserved + 0x00, // 0x80CD Reserved + 0x00, // 0x80CE Reserved + 0x00, // 0x80CF Reserved + 0x00, // 0x80D0 Reserved + 0x00, // 0x80D1 Reserved + 0x00, // 0x80D2 Reserved + 0x00, // 0x80D3 Reserved + 0x00, // 0x80D4 Reserved + 0x28, // 0x80D5 Driver CH0 + 0x26, // 0x80D6 Driver CH1 + 0x24, // 0x80D7 Driver CH2 + 0x22, // 0x80D8 Driver CH3 + 0x21, // 0x80D9 Driver CH4 + 0x20, // 0x80DA Driver CH5 + 0x1F, // 0x80DB Driver CH6 + 0x1E, // 0x80DC Driver CH7 + 0x1D, // 0x80DD Driver CH8 + 0x0C, // 0x80DE Driver CH9 + 0x0A, // 0x80DF Driver CH10 + 0x08, // 0x80E0 Driver CH11 + 0x06, // 0x80E1 Driver CH12 + 0x04, // 0x80E2 Driver CH13 + 0x02, // 0x80E3 Driver CH14 + 0x00, // 0x80E4 Driver CH15 + 0xFF, // 0x80E5 Driver CH16 + 0xFF, // 0x80E6 Driver CH17 + 0xFF, // 0x80E7 Driver CH18 + 0xFF, // 0x80E8 Driver CH19 + 0xFF, // 0x80E9 Driver CH20 + 0xFF, // 0x80EA Driver CH21 + 0xFF, // 0x80EB Driver CH22 + 0xFF, // 0x80EC Driver CH23 + 0xFF, // 0x80ED Driver CH24 + 0xFF, // 0x80EE Driver CH25 + 0x00, // 0x80EF Reserved + 0x00, // 0x80F0 Reserved + 0x00, // 0x80F1 Reserved + 0x00, // 0x80F2 Reserved + 0x00, // 0x80F3 Reserved + 0x00, // 0x80F4 Reserved + 0x00, // 0x80F5 Reserved + 0x00, // 0x80F6 Reserved + 0x00, // 0x80F7 Reserved + 0x00, // 0x80F8 Reserved + 0x00, // 0x80F9 Reserved + 0x00, // 0x80FA Reserved + 0x00, // 0x80FB Reserved + 0x00, // 0x80FC Reserved + 0x00, // 0x80FD Reserved + 0x00 // 0x80FE Reserved + }; //GT911 param table const uint8_t TOUCH_GT911_Cfg[] = @@ -438,53 +628,59 @@ bool touchPanelInit(void) { uint8_t tmp[4] = {0}; - TRACE("Touchpanel init start ..."); - - TOUCH_AF_GPIOConfig(); //SET RST=OUT INT=OUT INT=LOW - I2C_Init(); - - TPRST_LOW(); - TPINT_HIGH(); - delay_us(200); - - TPRST_HIGH(); - delay_ms(6); - - TPINT_LOW(); - delay_ms(55); - - TOUCH_AF_INT_Change(); //Set INT INPUT INT=LOW - - delay_ms(50); - - TRACE("Reading Touch registry"); - I2C_GT911_ReadRegister(GT_PID_REG, tmp, 4); - - if (strcmp((char *) tmp, "911") == 0) //ID==9147 - { - TRACE("GT911 chip detected"); - tmp[0] = 0X02; - I2C_GT911_WriteRegister(GT_CTRL_REG, tmp, 1); - I2C_GT911_ReadRegister(GT_CFGS_REG, tmp, 1); - - TRACE("Chip config Ver:%x\r\n",tmp[0]); - if (tmp[0] < GT911_CFG_NUMER) //Config ver - { - TRACE("Sending new config %d", GT911_CFG_NUMER); - I2C_GT911_SendConfig(1); - } - - delay_ms(10); - tmp[0] = 0X00; - I2C_GT911_WriteRegister(GT_CTRL_REG, tmp, 1); //end reset - touchGT911Flag = true; - + if (touchGT911Flag) { TOUCH_AF_ExtiConfig(); - return true; } - TRACE("GT911 chip NOT FOUND"); - return false; + else { + TRACE("Touchpanel init start ..."); + + TOUCH_AF_GPIOConfig(); //SET RST=OUT INT=OUT INT=LOW + I2C_Init(); + + TPRST_LOW(); + TPINT_HIGH(); + delay_us(200); + + TPRST_HIGH(); + delay_ms(6); + + TPINT_LOW(); + delay_ms(55); + + TOUCH_AF_INT_Change(); //Set INT INPUT INT=LOW + + delay_ms(50); + + TRACE("Reading Touch registry"); + I2C_GT911_ReadRegister(GT_PID_REG, tmp, 4); + + if (strcmp((char *) tmp, "911") == 0) //ID==9147 + { + TRACE("GT911 chip detected"); + tmp[0] = 0X02; + I2C_GT911_WriteRegister(GT_CTRL_REG, tmp, 1); + I2C_GT911_ReadRegister(GT_CFGS_REG, tmp, 1); + + TRACE("Chip config Ver:%x\r\n", tmp[0]); + if (tmp[0] < GT911_CFG_NUMER) //Config ver + { + TRACE("Sending new config %d", GT911_CFG_NUMER); + I2C_GT911_SendConfig(1); + } + + delay_ms(10); + tmp[0] = 0X00; + I2C_GT911_WriteRegister(GT_CTRL_REG, tmp, 1); //end reset + touchGT911Flag = true; + + TOUCH_AF_ExtiConfig(); + + return true; + } + TRACE("GT911 chip NOT FOUND"); + return false; + } } void touchPanelRead() diff --git a/radio/src/targets/horus/tp_gt911.h b/radio/src/targets/horus/tp_gt911.h index 4bfab4776..624db2c92 100644 --- a/radio/src/targets/horus/tp_gt911.h +++ b/radio/src/targets/horus/tp_gt911.h @@ -24,7 +24,7 @@ #define HAS_TOUCH_PANEL() touchGT911Flag == true extern uint8_t touchGT911Flag; -extern bool touchPanelInit(void); +extern bool touchPanelInit(); void touchPanelRead(); bool touchPanelEventOccured(); @@ -60,8 +60,7 @@ bool touchPanelEventOccured(); #define GT911_CONFIG_CHECKSUM_REG 0x80FF #define GT911_FIRMWARE_VERSION_REG 0x8144 -PACK(typedef struct -{ +PACK(typedef struct { uint8_t track; uint16_t x; uint16_t y; @@ -69,8 +68,7 @@ PACK(typedef struct uint8_t reserved; }) TouchPoint; -PACK(struct TouchData -{ +PACK(struct TouchData { uint8_t pointsCount; union { @@ -85,4 +83,4 @@ PACK(struct TouchData #define TPINT_LOW() do { TOUCH_INT_GPIO->BSRRH = TOUCH_INT_GPIO_PIN; } while(0) #define TPINT_HIGH() do { TOUCH_INT_GPIO->BSRRL = TOUCH_INT_GPIO_PIN; } while(0) -#endif // _FT5X06_H_ +#endif // _FT5X06_H_ \ No newline at end of file diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp index d5b34cc1e..a4f0c7b6b 100644 --- a/radio/src/targets/horus/trainer_driver.cpp +++ b/radio/src/targets/horus/trainer_driver.cpp @@ -20,6 +20,10 @@ #include "opentx.h" +#if defined(SBUS_TRAINER) +Fifo trainerSbusFifo; +#endif + void trainerSendNextFrame(); void init_trainer_ppm() @@ -102,7 +106,7 @@ void trainerSendNextFrame() { TRAINER_TIMER->CCR2 = GET_TRAINER_PPM_DELAY() * 2; TRAINER_TIMER->CCER = TIM_CCER_CC2E | (GET_TRAINER_PPM_POLARITY() ? 0 : TIM_CCER_CC2P); - TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance + TRAINER_TIMER->CCR3 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA TRAINER_DMA_STREAM->CR |= TRAINER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; @@ -119,8 +123,8 @@ extern "C" void TRAINER_DMA_IRQHandler() DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC); - TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag - TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt + TRAINER_TIMER->SR &= ~TIM_SR_CC3IF; // Clear flag + TRAINER_TIMER->DIER |= TIM_DIER_CC3IE; // Enable this interrupt } extern "C" void TRAINER_TIMER_IRQHandler() @@ -144,11 +148,23 @@ extern "C" void TRAINER_TIMER_IRQHandler() } // PPM out compare interrupt - if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) { + if ((TRAINER_TIMER->DIER & TIM_DIER_CC3IE) && (TRAINER_TIMER->SR & TIM_SR_CC3IF)) { // compare interrupt - TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt - TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag + TRAINER_TIMER->DIER &= ~TIM_DIER_CC3IE; // stop this interrupt + TRAINER_TIMER->SR &= ~TIM_SR_CC3IF; // Clear flag setupPulsesPPMTrainer(); trainerSendNextFrame(); } } + +int sbusGetByte(uint8_t * byte) +{ + switch (currentTrainerMode) { +#if defined(AUX_SERIAL) + case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: + return trainerSbusFifo.pop(*byte); +#endif + default: + return false; + } +} \ No newline at end of file diff --git a/radio/src/targets/nv14/hal.h b/radio/src/targets/nv14/hal.h index 462d4a2e2..a7a57b872 100644 --- a/radio/src/targets/nv14/hal.h +++ b/radio/src/targets/nv14/hal.h @@ -412,6 +412,7 @@ #define EXTMODULE_RX_GPIO GPIOC #define EXTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PC.07 #define EXTMODULE_RX_GPIO_PinSource GPIO_PinSource7 +#define EXTMODULE_USART USART6 #define EXTMODULE_RX_GPIO_AF_USART GPIO_AF_USART6 #define EXTMODULE_TIMER TIM8 #define EXTMODULE_TIMER_IRQn TIM8_CC_IRQn diff --git a/radio/src/targets/nv14/hallStick_driver.cpp b/radio/src/targets/nv14/hallStick_driver.cpp index 4e0e8e044..ce2adcda8 100644 --- a/radio/src/targets/nv14/hallStick_driver.cpp +++ b/radio/src/targets/nv14/hallStick_driver.cpp @@ -19,7 +19,6 @@ */ #include "opentx.h" -#include "pulses/flysky.h" DMAFifo hallDMAFifo __DMA (HALL_DMA_Stream_RX); Fifo hallStickTxFifo; diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 96babf4be..d501cc249 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -613,10 +613,8 @@ class OpenTxSimulatorFactory: public SimulatorFactory return Board::BOARD_TARANIS_X9LITES; #elif defined(PCBX9LITE) return Board::BOARD_TARANIS_X9LITE; -#elif defined(PCBTARANIS) - return Board::BOARD_TARANIS_X9D; #else - return Board::BOARD_9X_M64; + return Board::BOARD_TARANIS_X9D; #endif } }; diff --git a/radio/src/targets/sky9x/CMakeLists.txt b/radio/src/targets/sky9x/CMakeLists.txt index cff6a53b9..64a41f0e0 100644 --- a/radio/src/targets/sky9x/CMakeLists.txt +++ b/radio/src/targets/sky9x/CMakeLists.txt @@ -13,6 +13,8 @@ set(TARGET_DIR sky9x) set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} 9x_bitmaps) set(PPM_LIMITS_SYMETRICAL YES) set(PXX1 YES) +set(AFHDS3 NO) +set(GHOST NO) add_definitions(-DDISABLE_MULTI_UPDATE) if(PCB STREQUAL 9XRPRO) diff --git a/radio/src/targets/sky9x/audio_driver.h b/radio/src/targets/sky9x/audio_driver.h index 122269af6..40ae5e3bb 100644 --- a/radio/src/targets/sky9x/audio_driver.h +++ b/radio/src/targets/sky9x/audio_driver.h @@ -21,6 +21,8 @@ #ifndef _AUDIO_DRIVER_H_ #define _AUDIO_DRIVER_H_ +#include + void audioInit() ; void audioEnd() ; void audioConsumeCurrentBuffer(); diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h index 77b2a719a..802dabb21 100644 --- a/radio/src/targets/sky9x/board.h +++ b/radio/src/targets/sky9x/board.h @@ -273,7 +273,7 @@ extern "C" { #endif // Backlight driver -#define backlightEnable() (PWM->PWM_CH_NUM[0].PWM_CDTY = g_eeGeneral.backlightBright) +#define backlightEnable() (PWM->PWM_CH_NUM[0].PWM_CDTY = currentBacklightBright) #define backlightDisable() (PWM->PWM_CH_NUM[0].PWM_CDTY = 100) #define isBacklightEnabled() (PWM->PWM_CH_NUM[0].PWM_CDTY != 100) #define BACKLIGHT_ENABLE() backlightEnable() @@ -381,6 +381,7 @@ void pwrOn(); uint32_t pwrCheck(); bool pwrPressed(); #define UNEXPECTED_SHUTDOWN() (g_eeGeneral.unexpectedShutdown) +#define pwrForcePressed() (false) // EEPROM driver #define EEPROM_SIZE (4*1024*1024/8) diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 489360425..8aecbb55d 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -2,6 +2,8 @@ option(SHUTDOWN_CONFIRMATION "Shutdown confirmation" OFF) option(LCD_DUAL_BUFFER "Dual LCD Buffer" OFF) option(PXX1 "PXX1 protocol support" ON) option(PXX2 "PXX2 protocol support" OFF) +option(AFHDS3 "AFHDS3 TX Module" OFF) +option(GHOST "Ghost TX Module" ON) option(INTERNAL_MODULE_PPM "Support for PPM internal module" OFF) option(AUTOUPDATE "Auto update internal chips from SD" OFF) @@ -353,6 +355,7 @@ endif() add_definitions(-DPCBTARANIS) add_definitions(-DAUDIO -DVOICE -DRTCLOCK) +add_definitions(-DSBUS_TRAINER) set(SRC ${SRC} diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 5ebafccdc..d2b0847df 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -647,6 +647,7 @@ bool pwrPressed(); uint32_t pwrPressedDuration(); #endif void pwrResetHandler(); +#define pwrForcePressed() false #if defined(SIMU) #define UNEXPECTED_SHUTDOWN() false @@ -663,10 +664,10 @@ uint8_t isBacklightEnabled(); #define backlightEnable(...) #elif defined(PCBX9E) || defined(PCBX9DP) void backlightEnable(uint8_t level = 0, uint8_t color = 0); - #define BACKLIGHT_ENABLE() backlightEnable(g_eeGeneral.backlightBright, g_eeGeneral.backlightColor) + #define BACKLIGHT_ENABLE() backlightEnable(currentBacklightBright, g_eeGeneral.backlightColor) #else void backlightEnable(uint8_t level = 0); - #define BACKLIGHT_ENABLE() backlightEnable(g_eeGeneral.backlightBright) + #define BACKLIGHT_ENABLE() backlightEnable(currentBacklightBright) #endif #if !defined(SIMU) @@ -846,7 +847,7 @@ void ledBlue(); #define IS_LCD_RESET_NEEDED() true #define LCD_CONTRAST_MIN 10 #define LCD_CONTRAST_MAX 30 -#define LCD_CONTRAST_DEFAULT 20 +#define LCD_CONTRAST_DEFAULT 15 #endif #if defined(PCBX9D) || defined(PCBX9E) || (defined(PCBX9DP) && PCBREV < 2019) diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 19bd04525..a5b6a4acd 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -278,7 +278,25 @@ void extmoduleSendNextFrame() extmoduleSendBuffer(extmodulePulsesData.pxx2.getData(), extmodulePulsesData.pxx2.getSize()); break; #endif - +#if defined(AFHDS3) + case PROTOCOL_CHANNELS_AFHDS3: + { +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) + extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize()); +#else + const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData(); + uint32_t dataSize = extmodulePulsesData.afhds3.getSize(); + EXTMODULE_TIMER->CCR2 = dataPtr[dataSize -1] - 4000; // 2mS in advance + EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; + EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); + EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr); + EXTMODULE_TIMER_DMA_STREAM->NDTR = dataSize; + EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA +#endif + } + break; +#endif #if defined(SBUS) || defined(DSM2) || defined(MULTIMODULE) case PROTOCOL_CHANNELS_SBUS: EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? 0 : EXTMODULE_TIMER_OUTPUT_POLARITY); // reverse polarity for Sbus if needed @@ -303,6 +321,12 @@ void extmoduleSendNextFrame() break; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + sportSendBuffer(extmodulePulsesData.ghost.pulses, extmodulePulsesData.ghost.length); + break; +#endif + default: EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; break; diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 6fc3b994f..41d9ef1bf 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -928,6 +928,14 @@ #define GPIO_LED_GPIO_OFF GPIO_SetBits #define LED_RED_GPIO GPIOA #define LED_RED_GPIO_PIN GPIO_Pin_13 // PA.13 +#elif defined(PCBXLITES) + #define STATUS_LEDS + #define GPIO_LED_GPIO_ON GPIO_ResetBits + #define GPIO_LED_GPIO_OFF GPIO_SetBits + #define LED_BLUE_GPIO GPIOE + #define LED_BLUE_GPIO_PIN GPIO_Pin_6 // PE.06 + #define LED_RED_GPIO GPIOE + #define LED_RED_GPIO_PIN GPIO_Pin_4 // PE.04 #elif defined(PCBXLITE) #define STATUS_LEDS #define GPIO_LED_GPIO_ON GPIO_ResetBits @@ -1646,6 +1654,7 @@ #define BACKLIGHT_GPIO_PinSource GPIO_PinSource8 #define BACKLIGHT_GPIO_AF GPIO_AF_TIM10 #endif +#define KEYS_BACKLIGHT_RCC_AHB1Periph 0 // LCD driver #if defined(PCBX9E) diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp index ca66dc1a7..6936ae85f 100644 --- a/radio/src/targets/taranis/lcd_driver_spi.cpp +++ b/radio/src/targets/taranis/lcd_driver_spi.cpp @@ -144,9 +144,9 @@ void lcdStart() lcdWriteCommand(0xE9); // Set bias=1/10 lcdWriteCommand(0x81); // Set Vop #if defined(BOOT) - lcdWriteCommand(LCD_CONTRAST_OFFSET+LCD_CONTRAST_DEFAULT); + lcdWriteCommand(LCD_CONTRAST_OFFSET + LCD_CONTRAST_DEFAULT); #else - lcdWriteCommand(LCD_CONTRAST_OFFSET+g_eeGeneral.contrast); + lcdWriteCommand(LCD_CONTRAST_OFFSET + g_eeGeneral.contrast); #endif lcdWriteCommand(0xA2); // Set line rate: 28KLPS lcdWriteCommand(0x28); // Set panel loading @@ -173,11 +173,11 @@ void lcdStart() void lcdWriteAddress(uint8_t x, uint8_t y) { - lcdWriteCommand(x & 0x0F); // Set Column Address LSB CA[3:0] - lcdWriteCommand((x>>4) | 0x10); // Set Column Address MSB CA[7:4] + lcdWriteCommand(x & 0x0Fu); // Set Column Address LSB CA[3:0] + lcdWriteCommand((x >> 4u) | 0x10u); // Set Column Address MSB CA[7:4] - lcdWriteCommand((y&0x0F) | 0x60); // Set Row Address LSB RA [3:0] - lcdWriteCommand(((y>>4) & 0x0F) | 0x70); // Set Row Address MSB RA [7:4] + lcdWriteCommand((y & 0x0Fu) | 0x60u); // Set Row Address LSB RA [3:0] + lcdWriteCommand(((y >> 4u) & 0x0Fu) | 0x70u); // Set Row Address MSB RA [7:4] } #endif diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index e5b0d8cfe..f0068232b 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -40,7 +40,8 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) USART_DeInit(TELEMETRY_USART); return; } - + //deinit inverted mode + telemetryPortInvertedInit(0); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; @@ -87,11 +88,10 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) // soft serial vars static uint8_t rxBitCount; static uint8_t rxByte; +// single bit length expresses in half us +static uint16_t bitLength; +static uint16_t probeTimeFromStartBit; -//TODO: -// - only 57600 supported for now -// - handle other bitrates as well? -// void telemetryPortInvertedInit(uint32_t baudrate) { if (baudrate == 0) { @@ -116,6 +116,20 @@ void telemetryPortInvertedInit(uint32_t baudrate) rxBitCount = 0; + switch(baudrate) { + case 115200: + bitLength = 17; + probeTimeFromStartBit = 25; + break; + case 57600: + bitLength = 35; //34 was used before - I prefer to use use 35 because of lower error + probeTimeFromStartBit = 52; //round down - 48 used in original implementation + break; + default: + bitLength = 2000000/baudrate; //because of 0,5 us tick + probeTimeFromStartBit = 3000000/baudrate; + } + // configure bit sample timer TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS TELEMETRY_TIMER->CCER = 0; @@ -162,7 +176,7 @@ void telemetryPortInvertedRxBit() { if (rxBitCount < 8) { if (rxBitCount == 0) { - TELEMETRY_TIMER->ARR = 34; + TELEMETRY_TIMER->ARR = bitLength; rxByte = 0; } else { @@ -189,6 +203,11 @@ void telemetryPortInvertedRxBit() void telemetryPortSetDirectionOutput() { +#if defined(GHOST) && SPORT_MAX_BAUDRATE < 400000 + if (isModuleGhost(EXTERNAL_MODULE)) { + TELEMETRY_USART->BRR = BRR_400K; + } +#endif TELEMETRY_DIR_OUTPUT(); TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver } @@ -201,6 +220,11 @@ void sportWaitTransmissionComplete() void telemetryPortSetDirectionInput() { sportWaitTransmissionComplete(); +#if defined(GHOST) && SPORT_MAX_BAUDRATE < 400000 + if (isModuleGhost(EXTERNAL_MODULE) && g_eeGeneral.telemetryBaudrate == GHST_TELEMETRY_RATE_115K) { + TELEMETRY_USART->BRR = BRR_115K; + } +#endif TELEMETRY_DIR_INPUT(); TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver } @@ -333,7 +357,7 @@ void check_telemetry_exti() if (rxBitCount == 0) { - TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps + TELEMETRY_TIMER->ARR = probeTimeFromStartBit; // 1,5 cycle from start at 57600bps TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN; // disable start bit interrupt diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp index 06a006899..01f6e47bf 100644 --- a/radio/src/targets/taranis/trainer_driver.cpp +++ b/radio/src/targets/taranis/trainer_driver.cpp @@ -329,7 +329,7 @@ void stop_trainer_module_sbus() } #endif -#if defined(SBUS) +#if defined(SBUS_TRAINER) int sbusGetByte(uint8_t * byte) { switch (currentTrainerMode) { diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 0e7bd7a09..16e120784 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -76,7 +76,7 @@ bool isForcePowerOffRequested() bool isModuleSynchronous(uint8_t moduleIdx) { uint8_t protocol = moduleState[moduleIdx].protocol; - if (protocol == PROTOCOL_CHANNELS_PXX2_HIGHSPEED || protocol == PROTOCOL_CHANNELS_PXX2_LOWSPEED || protocol == PROTOCOL_CHANNELS_CROSSFIRE || protocol == PROTOCOL_CHANNELS_NONE) + if (protocol == PROTOCOL_CHANNELS_PXX2_HIGHSPEED || protocol == PROTOCOL_CHANNELS_PXX2_LOWSPEED || protocol == PROTOCOL_CHANNELS_CROSSFIRE || protocol == PROTOCOL_CHANNELS_GHOST || protocol == PROTOCOL_CHANNELS_NONE) return true; #if defined(INTMODULE_USART) || defined(EXTMODULE_USART) if (protocol == PROTOCOL_CHANNELS_PXX1_SERIAL) @@ -107,7 +107,7 @@ TASK_FUNCTION(mixerTask) s_pulses_paused = true; while (true) { -#if defined(PCBTARANIS) && defined(SBUS) +#if defined(SBUS_TRAINER) // SBUS trainer processSbusInput(); #endif diff --git a/radio/src/tasks.h b/radio/src/tasks.h index 921958363..856aaf038 100644 --- a/radio/src/tasks.h +++ b/radio/src/tasks.h @@ -24,7 +24,11 @@ #include "rtos.h" // stack sizes should be in multiples of 8 for better alignment -#define MENUS_STACK_SIZE 2000 +#if defined (COLORLCD) + #define MENUS_STACK_SIZE 4000 +#else + #define MENUS_STACK_SIZE 2000 +#endif #define MIXER_STACK_SIZE 400 #define AUDIO_STACK_SIZE 400 #define CLI_STACK_SIZE 1000 // only consumed with CLI build option diff --git a/radio/src/telemetry/crossfire.cpp b/radio/src/telemetry/crossfire.cpp index 291af37bf..265045130 100644 --- a/radio/src/telemetry/crossfire.cpp +++ b/radio/src/telemetry/crossfire.cpp @@ -106,6 +106,10 @@ void processCrossfireTelemetryFrame() return; } + if (telemetryState == TELEMETRY_INIT && moduleState[EXTERNAL_MODULE].counter != CRSF_FRAME_MODELID_SENT) { + moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID; + } + uint8_t id = telemetryRxBuffer[2]; int32_t value; switch(id) { diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h index 7dedd6141..347104980 100644 --- a/radio/src/telemetry/crossfire.h +++ b/radio/src/telemetry/crossfire.h @@ -40,7 +40,12 @@ #define PING_DEVICES_ID 0x28 #define DEVICE_INFO_ID 0x29 #define REQUEST_SETTINGS_ID 0x2A +#define COMMAND_ID 0x32 +#define RADIO_ID 0x3A +#define UART_SYNC 0xC8 +#define SUBCOMMAND_CRSF 0x10 +#define COMMAND_MODEL_SELECT_ID 0x05 struct CrossfireSensor { const uint8_t id; @@ -79,8 +84,15 @@ enum CrossfireSensorIndexes { UNKNOWN_INDEX, }; +enum CrossfireFrames{ + CRSF_FRAME_CHANNEL, + CRSF_FRAME_MODELID, + CRSF_FRAME_MODELID_SENT +}; + void processCrossfireTelemetryData(uint8_t data); void crossfireSetDefault(int index, uint8_t id, uint8_t subId); +uint8_t createCrossfireModelIDFrame(uint8_t * frame); const uint32_t CROSSFIRE_BAUDRATES[] = { 400000, diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index a6158ccfb..4f0fc4450 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -61,7 +61,8 @@ enum AFHDS2A_ID_GPS_DIST = 0x14, // 2 bytes distance from home m unsigned AFHDS2A_ID_ARMED = 0x15, // 2 bytes AFHDS2A_ID_FLIGHT_MODE = 0x16, // 2 bytes - + AFHDS3_FRM_TEMP = 0x57, //virtual + AFHDS3_FRM_EXT_V = 0x58, //virtual AFHDS2A_ID_PRES = 0x41, // Pressure AFHDS2A_ID_ODO1 = 0x7C, // Odometer1 AFHDS2A_ID_ODO2 = 0x7D, // Odometer2 @@ -79,8 +80,9 @@ enum AFHDS2A_ID_S88 = 0x88, AFHDS2A_ID_S89 = 0x89, AFHDS2A_ID_S8a = 0x8A, - - AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX - SIGNED value + AFHDS2A_ID_RX_SIG_AFHDS3 = 0xF7, // SIG + AFHDS2A_ID_RX_SNR_AFHDS3 = 0xF8, // SNR + AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX AFHDS2A_ID_RX_SNR = 0xFA, // SNR AFHDS2A_ID_RX_NOISE = 0xFB, // Noise AFHDS2A_ID_RX_RSSI = 0xFC, // RSSI @@ -120,6 +122,8 @@ const FlySkySensor flySkySensors[] = { {AFHDS2A_ID_FLIGHT_MODE, STR_SENSOR_FLIGHT_MODE, UNIT_RAW, 0}, // 2 bytes index {AFHDS2A_ID_PRES, STR_SENSOR_PRES, UNIT_RAW, 2}, // 4 bytes In fact Temperature + Pressure -> Altitude {AFHDS2A_ID_PRES | 0x100, STR_SENSOR_TEMP2, UNIT_CELSIUS, 1}, // 2 bytes Temperature + {AFHDS3_FRM_TEMP, ZSTR_TEMP2, UNIT_CELSIUS, 1}, // 2 bytes temperature + {AFHDS3_FRM_EXT_V, ZSTR_TXV, UNIT_VOLTS, 2}, // 2 bytes voltage {AFHDS2A_ID_ODO1, STR_SENSOR_ODO1, UNIT_METERS, 2}, // 2 bytes Odometer1 -- some magic with 330 needed {AFHDS2A_ID_ODO2, STR_SENSOR_ODO2, UNIT_METERS, 2}, // 2 bytes Odometer2 -- some magic with 330 needed {AFHDS2A_ID_SPE, STR_SENSOR_ASPD, UNIT_KMH, 2}, // 2 bytes Speed km/h -- some magic with 330 needed @@ -128,7 +132,8 @@ const FlySkySensor flySkySensors[] = { {AFHDS2A_ID_GPS_LON, STR_SENSOR_GPS, UNIT_RAW, 7}, // 4 bytes signed WGS84 in degrees * 1E7 {AFHDS2A_ID_GPS_ALT, STR_SENSOR_GPSALT, UNIT_METERS, 2}, // 4 bytes signed GPS alt m*100 {AFHDS2A_ID_ALT, STR_SENSOR_ALT, UNIT_METERS, 2}, // 4 bytes signed Alt m*100 - + {AFHDS2A_ID_RX_SIG_AFHDS3, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX error rate + {AFHDS2A_ID_RX_SNR_AFHDS3, ZSTR_RX_SNR, UNIT_DB, 1}, // RX SNR {AFHDS2A_ID_RX_SNR, STR_SENSOR_RX_SNR, UNIT_DB, 0}, // RX SNR {AFHDS2A_ID_RX_NOISE, STR_SENSOR_RX_NOISE, UNIT_DB, 0}, // RX Noise {AFHDS2A_ID_RX_RSSI, STR_SENSOR_RSSI, UNIT_DB, 0}, // RX RSSI (0xfc) @@ -140,7 +145,7 @@ const FlySkySensor flySkySensors[] = { int32_t getALT(uint32_t value); -static void processFlySkySensor(const uint8_t * packet, uint8_t type) +void processFlySkySensor(const uint8_t * packet, uint8_t type) { uint8_t buffer[8]; uint16_t id = packet[0]; @@ -156,13 +161,17 @@ static void processFlySkySensor(const uint8_t * packet, uint8_t type) if (id == 0) id = 0x100; // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100 if (id == AFHDS2A_ID_RX_NOISE || id == AFHDS2A_ID_RX_RSSI) { - value = -value; + value = 135 - value; } else if (id == AFHDS2A_ID_RX_ERR_RATE) { value = 100 - value; telemetryData.rssi.set(value); if (value > 0) telemetryStreaming = TELEMETRY_TIMEOUT10ms; } + else if(id == AFHDS2A_ID_RX_SIG_AFHDS3) { + telemetryData.rssi.set(value); + if(value>0) telemetryStreaming = TELEMETRY_TIMEOUT10ms; + } else if (id == AFHDS2A_ID_PRES && value) { // Extract temperature to a new sensor setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id | 0x100, 0, instance, ((value >> 19) - 400), UNIT_CELSIUS, 1); @@ -216,7 +225,7 @@ static void processFlySkySensor(const uint8_t * packet, uint8_t type) for (const FlySkySensor * sensor = flySkySensors; sensor->id; sensor++) { if (sensor->id != id) continue; if (sensor->unit == UNIT_CELSIUS) value -= 400; // Temperature sensors have 40 degree offset - else if (sensor->unit == UNIT_VOLTS) value = (uint16_t) value; // Voltage types are unsigned 16bit integers + else if (sensor->unit == UNIT_VOLTS) value = (int16_t) value; // Voltage types are unsigned 16bit integers setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id, 0, instance, value, sensor->unit, sensor->precision); return; } @@ -390,4 +399,4 @@ int32_t getALT(uint32_t value) if (neg ^ tempNegative) result = result * -1; return result; -} \ No newline at end of file +} diff --git a/radio/src/telemetry/flysky_ibus.h b/radio/src/telemetry/flysky_ibus.h index bfb0db640..dd30e0058 100644 --- a/radio/src/telemetry/flysky_ibus.h +++ b/radio/src/telemetry/flysky_ibus.h @@ -21,6 +21,8 @@ #ifndef _FLYSKY_IBUS_H #define _FLYSKY_IBUS_H +void processFlySkySensor(const uint8_t *packet, uint8_t type); + void processFlySkyTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBufferCount); void flySkySetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance); diff --git a/radio/src/telemetry/flysky_nv14.cpp b/radio/src/telemetry/flysky_nv14.cpp index 5f75142a9..059abbbaf 100644 --- a/radio/src/telemetry/flysky_nv14.cpp +++ b/radio/src/telemetry/flysky_nv14.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "flysky_nv14.h" #define FLYSKY_FIXED_RX_VOLTAGE (uint8_t)(FLYSKY_SENSOR_RX_VOLTAGE + (uint8_t)0xA0) diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h index 751196d1c..8621869c6 100644 --- a/radio/src/telemetry/frsky.h +++ b/radio/src/telemetry/frsky.h @@ -139,6 +139,8 @@ enum FrSkyDataState { #define A4_LAST_ID 0x091F #define AIR_SPEED_FIRST_ID 0x0A00 #define AIR_SPEED_LAST_ID 0x0A0F +#define FUEL_QTY_FIRST_ID 0x0A10 +#define FUEL_QTY_LAST_ID 0x0A1F #define RBOX_BATT1_FIRST_ID 0x0B00 #define RBOX_BATT1_LAST_ID 0x0B0F #define RBOX_BATT2_FIRST_ID 0x0B10 @@ -152,9 +154,9 @@ enum FrSkyDataState { #define ESC_POWER_FIRST_ID 0x0B50 #define ESC_POWER_LAST_ID 0x0B5F #define ESC_RPM_CONS_FIRST_ID 0x0B60 -#define ESC_RPM_CONS_LAST_ID 0x0B6f +#define ESC_RPM_CONS_LAST_ID 0x0B6F #define ESC_TEMPERATURE_FIRST_ID 0x0B70 -#define ESC_TEMPERATURE_LAST_ID 0x0B7f +#define ESC_TEMPERATURE_LAST_ID 0x0B7F #define RB3040_OUTPUT_FIRST_ID 0x0B80 #define RB3040_OUTPUT_LAST_ID 0x0B8F #define RB3040_CH1_2_FIRST_ID 0x0B90 @@ -165,10 +167,10 @@ enum FrSkyDataState { #define RB3040_CH5_6_LAST_ID 0x0BBF #define RB3040_CH7_8_FIRST_ID 0x0BC0 #define RB3040_CH7_8_LAST_ID 0x0BCF -#define X8R_FIRST_ID 0x0c20 -#define X8R_LAST_ID 0x0c2F -#define S6R_FIRST_ID 0x0c30 -#define S6R_LAST_ID 0x0c3F +#define X8R_FIRST_ID 0x0C20 +#define X8R_LAST_ID 0x0C2F +#define S6R_FIRST_ID 0x0C30 +#define S6R_LAST_ID 0x0C3F #define GASSUIT_TEMP1_FIRST_ID 0x0D00 #define GASSUIT_TEMP1_LAST_ID 0x0D0F #define GASSUIT_TEMP2_FIRST_ID 0x0D10 @@ -182,15 +184,17 @@ enum FrSkyDataState { #define GASSUIT_FLOW_FIRST_ID 0x0D50 #define GASSUIT_FLOW_LAST_ID 0x0D5F #define GASSUIT_MAX_FLOW_FIRST_ID 0x0D60 -#define GASSUIT_MAX_FLOW_LAST_ID 0x0D6f +#define GASSUIT_MAX_FLOW_LAST_ID 0x0D6F #define GASSUIT_AVG_FLOW_FIRST_ID 0x0D70 -#define GASSUIT_AVG_FLOW_LAST_ID 0x0D7f +#define GASSUIT_AVG_FLOW_LAST_ID 0x0D7F #define SBEC_POWER_FIRST_ID 0x0E50 #define SBEC_POWER_LAST_ID 0x0E5F #define DIY_FIRST_ID 0x5100 #define DIY_LAST_ID 0x52FF #define DIY_STREAM_FIRST_ID 0x5000 #define DIY_STREAM_LAST_ID 0x50FF +#define SERVO_FIRST_ID 0x6800 +#define SERVO_LAST_ID 0x680F #define FACT_TEST_ID 0xF000 #define VALID_FRAME_RATE_ID 0xF010 #define RSSI_ID 0xF101 @@ -202,8 +206,6 @@ enum FrSkyDataState { #define R9_PWR_ID 0xF107 #define SP2UART_A_ID 0xFD00 #define SP2UART_B_ID 0xFD01 -#define FUEL_QTY_FIRST_ID 0x0A10 -#define FUEL_QTY_LAST_ID 0x0A1F #if defined(MULTIMODULE) // Virtual IDs, value can be changed to anything only used for display diff --git a/radio/src/telemetry/frsky_pxx2.cpp b/radio/src/telemetry/frsky_pxx2.cpp index 3557fe84b..cbfae9ab9 100644 --- a/radio/src/telemetry/frsky_pxx2.cpp +++ b/radio/src/telemetry/frsky_pxx2.cpp @@ -92,6 +92,9 @@ void processReceiverSettingsFrame(uint8_t module, const uint8_t * frame) if (frame[4] & PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6) destination->enablePwmCh5Ch6 = 1; + if (frame[4] & PXX2_RX_SETTINGS_FLAG1_FPORT2) + destination->fport2 = 1; + uint8_t outputsCount = min(16, frame[0] - 4); destination->outputsCount = outputsCount; for (uint8_t pin = 0; pin < outputsCount; pin++) { diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index d9bc12ae7..123945b4c 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -48,9 +48,9 @@ const FrSkySportSensor sportSensors[] = { { FUEL_FIRST_ID, FUEL_LAST_ID, 0, STR_SENSOR_FUEL, UNIT_PERCENT, 0 }, { ALT_FIRST_ID, ALT_LAST_ID, 0, STR_SENSOR_ALT, UNIT_METERS, 2 }, { VARIO_FIRST_ID, VARIO_LAST_ID, 0, STR_SENSOR_VSPD, UNIT_METERS_PER_SECOND, 2 }, - { ACCX_FIRST_ID, ACCX_LAST_ID, 0, STR_SENSOR_ACCX, UNIT_G, 2 }, - { ACCY_FIRST_ID, ACCY_LAST_ID, 0, STR_SENSOR_ACCY, UNIT_G, 2 }, - { ACCZ_FIRST_ID, ACCZ_LAST_ID, 0, STR_SENSOR_ACCZ, UNIT_G, 2 }, + { ACCX_FIRST_ID, ACCX_LAST_ID, 0, STR_SENSOR_ACCX, UNIT_G, 3 }, + { ACCY_FIRST_ID, ACCY_LAST_ID, 0, STR_SENSOR_ACCY, UNIT_G, 3 }, + { ACCZ_FIRST_ID, ACCZ_LAST_ID, 0, STR_SENSOR_ACCZ, UNIT_G, 3 }, { CURR_FIRST_ID, CURR_LAST_ID, 0, STR_SENSOR_CURR, UNIT_AMPS, 1 }, { VFAS_FIRST_ID, VFAS_LAST_ID, 0, STR_SENSOR_VFAS, UNIT_VOLTS, 2 }, { AIR_SPEED_FIRST_ID, AIR_SPEED_LAST_ID, 0, STR_SENSOR_ASPD, UNIT_KTS, 1 }, @@ -94,7 +94,11 @@ const FrSkySportSensor sportSensors[] = { { RB3040_CH5_6_FIRST_ID, RB3040_CH5_6_LAST_ID, 1, ZSTR_RB3040_CHANNEL6, UNIT_AMPS, 2 }, { RB3040_CH7_8_FIRST_ID, RB3040_CH7_8_LAST_ID, 0, ZSTR_RB3040_CHANNEL7, UNIT_AMPS, 2 }, { RB3040_CH7_8_FIRST_ID, RB3040_CH7_8_LAST_ID, 1, ZSTR_RB3040_CHANNEL8, UNIT_AMPS, 2 }, - { 0, 0, 0, NULL, UNIT_RAW, 0 } // sentinel + { SERVO_FIRST_ID, SERVO_LAST_ID, 0, ZSTR_SERVO_CURRENT, UNIT_AMPS, 1 }, + { SERVO_FIRST_ID, SERVO_LAST_ID, 1, ZSTR_SERVO_VOLTAGE, UNIT_VOLTS, 1 }, + { SERVO_FIRST_ID, SERVO_LAST_ID, 2, ZSTR_SERVO_TEMPERATURE, UNIT_CELSIUS, 0 }, + { SERVO_FIRST_ID, SERVO_LAST_ID, 3, ZSTR_SERVO_STATUS, UNIT_TEXT, 0 }, + { 0, 0, 0, nullptr, UNIT_RAW, 0 } // sentinel }; const FrSkySportSensor * getFrSkySportSensor(uint16_t id, uint8_t subId=0) @@ -110,13 +114,13 @@ const FrSkySportSensor * getFrSkySportSensor(uint16_t id, uint8_t subId=0) bool checkSportPacket(const uint8_t * packet) { short crc = 0; - for (int i=1; i> 8; // 0-1FF - crc &= 0x00ff; // 0-FF + crc += crc >> 8u; // 0-1FF + crc &= 0x00FFu; // 0-FF } // TRACE("crc: 0x%02x", crc); - return (crc == 0x00ff); + return crc == 0x00FF; } #define SPORT_DATA_U8(packet) (packet[4]) @@ -137,15 +141,15 @@ void sportProcessTelemetryPacket(uint16_t id, uint8_t subId, uint8_t instance, u precision = sensor->prec; } if (unit == UNIT_CELLS) { - uint8_t cellsCount = (data & 0xF0) >> 4; - uint8_t cellIndex = (data & 0x0F); + uint8_t cellsCount = (data & 0xF0u) >> 4u; + uint8_t cellIndex = (data & 0x0Fu); if (cellIndex >= MAX_CELLS) return; - uint32_t mask = (cellsCount << 24) + (cellIndex << 16); - setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0x000FFF00) >> 8) / 5), unit, precision); - if (cellIndex+1 < cellsCount) { - mask += (1 << 16); - setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0xFFF00000) >> 20) / 5), unit, precision); + uint32_t mask = (cellsCount << 24u) + (cellIndex << 16u); + setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0x000FFF00u) >> 8u) / 5), unit, precision); + if (cellIndex + 1 < cellsCount) { + mask += (1 << 16u); + setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0xFFF00000u) >> 20u) / 5), unit, precision); } } else { @@ -219,7 +223,7 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe } #if defined(MULTIMODULE) if (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE) { - sportProcessTelemetryPacket(TX_RSSI_ID, 0, instance, packet[5] >> 1, UNIT_DB); + sportProcessTelemetryPacket(TX_RSSI_ID, 0, instance, packet[5] >> 1u, UNIT_DB); sportProcessTelemetryPacket(TX_LQI_ID, 0, instance, packet[7], UNIT_RAW); } #endif @@ -263,40 +267,40 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe if (dataId >= GPS_LONG_LATI_FIRST_ID && dataId <= GPS_LONG_LATI_LAST_ID) { int32_t value = (data & 0x3fffffff); - if (data & (1 << 30)) + if (data & (1 << 30u)) value = -value; value = (value * 5) / 3; // min/10000 => deg/1000000 - if (data & (1 << 31)) + if (data & (1 << 31u)) sportProcessTelemetryPacket(dataId, 0, instance, value, UNIT_GPS_LONGITUDE); else sportProcessTelemetryPacket(dataId, 0, instance, value, UNIT_GPS_LATITUDE); } else if (dataId >= RBOX_BATT1_FIRST_ID && dataId <= RBOX_BATT2_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, data & 0xffff); - sportProcessTelemetryPacket(dataId, 1, instance, data >> 16); + sportProcessTelemetryPacket(dataId, 0, instance, data & 0xFFFFu); + sportProcessTelemetryPacket(dataId, 1, instance, data >> 16u); } else if (dataId >= RBOX_CNSP_FIRST_ID && dataId <= RBOX_CNSP_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, data & 0xffff); - sportProcessTelemetryPacket(dataId, 1, instance, data >> 16); + sportProcessTelemetryPacket(dataId, 0, instance, data & 0xFFFFu); + sportProcessTelemetryPacket(dataId, 1, instance, data >> 16u); } else if (dataId >= RBOX_STATE_FIRST_ID && dataId <= RBOX_STATE_LAST_ID) { bool static isRB10 = false; uint16_t newServosState; - if (servosState == 0 && (data & 0xff00) == 0xff00) { + if (servosState == 0 && (data & 0xFF00u) == 0xFF00u) { isRB10 = true; } if (isRB10) { - newServosState = data & 0x00ff; // 8ch only RB10 + newServosState = data & 0x00FFu; // 8ch only RB10 } else { - newServosState = data & 0xffff; + newServosState = data & 0xFFFFu; } if (newServosState != 0 && servosState == 0) { audioEvent(AU_SERVO_KO); } - uint16_t newRboxState = data >> 16; - if ((newRboxState & 0x07) && (rboxState & 0x07) == 0) { + uint16_t newRboxState = data >> 16u; + if ((newRboxState & 0x07u) && (rboxState & 0x07u) == 0) { audioEvent(AU_RX_OVERLOAD); } servosState = newServosState; @@ -305,19 +309,19 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe sportProcessTelemetryPacket(dataId, 1, instance, rboxState); } else if (dataId >= ESC_POWER_FIRST_ID && dataId <= ESC_POWER_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, data & 0xffff); - sportProcessTelemetryPacket(dataId, 1, instance, data >> 16); + sportProcessTelemetryPacket(dataId, 0, instance, data & 0xFFFFu); + sportProcessTelemetryPacket(dataId, 1, instance, data >> 16u); } else if (dataId >= ESC_RPM_CONS_FIRST_ID && dataId <= ESC_RPM_CONS_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, 100 * (data & 0xffff)); - sportProcessTelemetryPacket(dataId, 1, instance, data >> 16); + sportProcessTelemetryPacket(dataId, 0, instance, 100 * (data & 0xFFFFu)); + sportProcessTelemetryPacket(dataId, 1, instance, data >> 16u); } else if (dataId >= ESC_TEMPERATURE_FIRST_ID && dataId <= ESC_TEMPERATURE_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, data & 0x00ff); + sportProcessTelemetryPacket(dataId, 0, instance, data & 0x00FFu); } else if (dataId >= SBEC_POWER_FIRST_ID && dataId <= SBEC_POWER_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, (data & 0xffff) / 10); - sportProcessTelemetryPacket(dataId, 1, instance, (data >> 16) / 10); + sportProcessTelemetryPacket(dataId, 0, instance, (data & 0xFFFFu) / 10); + sportProcessTelemetryPacket(dataId, 1, instance, (data >> 16u) / 10); } else if (dataId >= DIY_STREAM_FIRST_ID && dataId <= DIY_STREAM_LAST_ID) { #if defined(LUA) @@ -334,8 +338,19 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe #endif } else if (dataId >= RB3040_CH1_2_FIRST_ID && dataId <= RB3040_CH7_8_LAST_ID) { - sportProcessTelemetryPacket(dataId, 0, instance, data & 0xffff); - sportProcessTelemetryPacket(dataId, 1, instance, (data >> 16u) & 0xffff); + sportProcessTelemetryPacket(dataId, 0, instance, data & 0xFFFFu); + sportProcessTelemetryPacket(dataId, 1, instance, (data >> 16u) & 0xFFFFu); + } + else if (dataId >= SERVO_FIRST_ID && dataId <= SERVO_LAST_ID) { + sportProcessTelemetryPacket(dataId, 0, instance, data & 0xFFu); + sportProcessTelemetryPacket(dataId, 1, instance, (data >> 8u) & 0xFFu); + sportProcessTelemetryPacket(dataId, 2, instance, (data >> 16u) & 0xFFu); + uint8_t newServosState = data >> 24u; + setTelemetryText(PROTOCOL_TELEMETRY_FRSKY_SPORT, dataId, 3, instance, newServosState ? "STALL" : "OK"); + if (newServosState != 0 && servosState == 0) { + audioEvent(AU_SERVO_KO); + servosState = newServosState; + } } else { sportProcessTelemetryPacket(dataId, 0, instance, data); diff --git a/radio/src/telemetry/ghost.cpp b/radio/src/telemetry/ghost.cpp new file mode 100755 index 000000000..406db73d0 --- /dev/null +++ b/radio/src/telemetry/ghost.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" + +const char *ghstRfProfileValue[GHST_RF_PROFILE_COUNT] = { "Auto", "Norm", "Race", "Pure", "Long", "Unused", "Race2", "Pure2" }; +const char *ghstVtxBandName[GHST_VTX_BAND_COUNT] = { "- - -" , "IRC", "Race", "BandE", "BandB", "BandA" }; + +struct GhostSensor +{ + const uint16_t id; + const char * name; + const TelemetryUnit unit; + const uint8_t precision; +}; + +// telemetry sensors ID +enum +{ + GHOST_ID_RX_RSSI = 0x0001, // Rx-side RSSI + GHOST_ID_RX_LQ = 0x0002, // Rx-side link quality + GHOST_ID_RX_SNR = 0x0003, // Rx-side signal to noise + GHOST_ID_FRAME_RATE = 0x0004, // Tx-side frame rate + GHOST_ID_TX_POWER = 0x0005, // Tx-side power output + GHOST_ID_RF_MODE = 0x0006, // Tx-side frame rate + GHOST_ID_TOTAL_LATENCY = 0x0007, // Tx-side total latency + GHOST_ID_VTX_FREQ = 0x0008, // Vtx Frequency (in MHz) + GHOST_ID_VTX_POWER = 0x0009, // Vtx Power (in mW) + GHOST_ID_VTX_CHAN = 0x000a, // Vtx Channel + GHOST_ID_VTX_BAND = 0x000b, // Vtx Band + +}; + +const GhostSensor ghostSensors[] = { + {GHOST_ID_RX_RSSI, ZSTR_RSSI, UNIT_DB, 0}, + {GHOST_ID_RX_LQ, ZSTR_RX_QUALITY, UNIT_PERCENT, 0}, + {GHOST_ID_RX_SNR, ZSTR_RX_SNR, UNIT_DB, 0}, + + {GHOST_ID_FRAME_RATE, ZSTR_FRAME_RATE, UNIT_RAW, 0}, + {GHOST_ID_TX_POWER, ZSTR_TX_POWER, UNIT_MILLIWATTS, 0}, + {GHOST_ID_RF_MODE, ZSTR_RF_MODE, UNIT_TEXT, 0}, + {GHOST_ID_TOTAL_LATENCY, ZSTR_TOTAL_LATENCY, UNIT_RAW, 0}, + + {GHOST_ID_VTX_FREQ, ZSTR_VTX_FREQ, UNIT_RAW, 0}, + {GHOST_ID_VTX_POWER, ZSTR_VTX_PWR, UNIT_RAW, 0}, + {GHOST_ID_VTX_CHAN, ZSTR_VTX_CHAN, UNIT_RAW, 0}, + {GHOST_ID_VTX_BAND, ZSTR_VTX_BAND, UNIT_TEXT, 0}, + + {0x00, NULL, UNIT_RAW, 0}, +}; + +const GhostSensor *getGhostSensor(uint8_t id) +{ + for (const GhostSensor * sensor = ghostSensors; sensor->id; sensor++) { + if (id == sensor->id) + return sensor; + } + return nullptr; +} + +void processGhostTelemetryValue(uint8_t index, int32_t value) +{ + if (!TELEMETRY_STREAMING()) + return; + + const GhostSensor * sensor = getGhostSensor(index); + setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, sensor->id, 0, 0, value, sensor->unit, sensor->precision); +} + +void processGhostTelemetryValueString(const GhostSensor * sensor, const char * str) +{ + if (TELEMETRY_STREAMING()) { + setTelemetryText(PROTOCOL_TELEMETRY_GHOST, sensor->id, 0, 0, str); + } +} + +bool checkGhostTelemetryFrameCRC() +{ + uint8_t len = telemetryRxBuffer[1]; + uint8_t crc = crc8(&telemetryRxBuffer[2], len - 1); + return (crc == telemetryRxBuffer[len + 1]); +} + +uint16_t getTelemetryValue_u16(uint8_t index) +{ + return (telemetryRxBuffer[index] << 8) | telemetryRxBuffer[index + 1]; +} + +uint32_t getTelemetryValue_s32(uint8_t index) +{ + uint32_t val = 0; + for (int i = 0; i < 4; ++i) + val <<= 8, val |= telemetryRxBuffer[index + i]; + return val; +} + +void processGhostTelemetryFrame() +{ + if (!checkGhostTelemetryFrameCRC()) { + TRACE("[GS] CRC error"); + return; + } + + uint8_t id = telemetryRxBuffer[2]; + switch(id) { + case GHST_DL_LINK_STAT: + { +#if defined(BLUETOOTH) + if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) { + bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount); + } +#endif + uint8_t rssiVal = min(telemetryRxBuffer[3], 120); // RSSI is a negative value, but sent as a positive integer. + uint8_t lqVal = min(telemetryRxBuffer[4], 100); + uint8_t snrVal = min(telemetryRxBuffer[5], 100); + + processGhostTelemetryValue(GHOST_ID_RX_RSSI, - rssiVal); + processGhostTelemetryValue(GHOST_ID_RX_LQ, lqVal); + processGhostTelemetryValue(GHOST_ID_RX_SNR, snrVal); + + // give OpenTx the LQ value, not RSSI + if (lqVal) { + telemetryData.rssi.set(lqVal); + telemetryStreaming = TELEMETRY_TIMEOUT10ms; + } + else { + telemetryData.rssi.reset(); + telemetryStreaming = 0; + } + + processGhostTelemetryValue(GHOST_ID_TX_POWER, getTelemetryValue_u16(6)); + processGhostTelemetryValue(GHOST_ID_FRAME_RATE, getTelemetryValue_u16(8)); + processGhostTelemetryValue(GHOST_ID_TOTAL_LATENCY, getTelemetryValue_u16(10)); + uint8_t rfModeEnum = min(telemetryRxBuffer[12], GHST_RF_PROFILE_MAX); + + // RF mode string, one char at a time + const GhostSensor * sensor = getGhostSensor(GHOST_ID_RF_MODE); + const char * rfModeString = ghstRfProfileValue[rfModeEnum]; + processGhostTelemetryValueString(sensor, rfModeString); + break; + } + + case GHST_DL_VTX_STAT: + { +#if defined(BLUETOOTH) + if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) { + bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount); + } +#endif + uint8_t vtxBandEnum = min(telemetryRxBuffer[8], GHST_VTX_BAND_MAX); + + const GhostSensor * sensor = getGhostSensor(GHOST_ID_VTX_BAND); + const char * vtxBandString = ghstVtxBandName[vtxBandEnum]; + + processGhostTelemetryValue(GHOST_ID_VTX_FREQ, getTelemetryValue_u16(4)); + processGhostTelemetryValue(GHOST_ID_VTX_POWER, getTelemetryValue_u16(6)); + processGhostTelemetryValue(GHOST_ID_VTX_CHAN, min(telemetryRxBuffer[9], 8)); + processGhostTelemetryValueString(sensor, vtxBandString); + break; + } + } +} + +void processGhostTelemetryData(uint8_t data) +{ +#if defined(AUX_SERIAL) + if (g_eeGeneral.auxSerialMode == UART_MODE_TELEMETRY_MIRROR) { + auxSerialPutc(data); + } +#endif + +#if defined(AUX2_SERIAL) + if (g_eeGeneral.aux2SerialMode == UART_MODE_TELEMETRY_MIRROR) { + aux2SerialPutc(data); + } +#endif + + if (telemetryRxBufferCount == 0 && data != GHST_ADDR_RADIO) { + TRACE("[GH] address 0x%02X error", data); + return; + } + + if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + telemetryRxBuffer[telemetryRxBufferCount++] = data; + } + else { + TRACE("[GH] array size %d error", telemetryRxBufferCount); + telemetryRxBufferCount = 0; + } + + if (telemetryRxBufferCount > 4) { + uint8_t length = telemetryRxBuffer[1]; + if (length + 2 == telemetryRxBufferCount) { + processGhostTelemetryFrame(); + telemetryRxBufferCount = 0; + } + } +} + + +void ghostSetDefault(int index, uint8_t id, uint8_t subId) +{ + TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index]; + + telemetrySensor.id = id; + telemetrySensor.instance = subId; + + const GhostSensor * sensor = getGhostSensor(id); + if (sensor) { + TelemetryUnit unit = sensor->unit; + uint8_t prec = min(2, sensor->precision); + telemetrySensor.init(sensor->name, unit, prec); + } + else + telemetrySensor.init(id); + + storageDirty(EE_MODEL); +} diff --git a/radio/src/telemetry/ghost.h b/radio/src/telemetry/ghost.h new file mode 100755 index 000000000..9fcd54120 --- /dev/null +++ b/radio/src/telemetry/ghost.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _GHOST_H_ +#define _GHOST_H_ + +#include +#include "dataconstants.h" + +// Device (destination) address +#define GHST_ADDR_RADIO 0x80 // phase 1 +#define GHST_ADDR_MODULE_SYM 0x81 // symmetrical, 400k pulses, 400k telemetry +#define GHST_ADDR_MODULE_ASYM 0x88 // asymmetrical, 400k pulses, 115k telemetry +#define GHST_ADDR_FC 0x82 +#define GHST_ADDR_GOGGLES 0x83 // phase 2 +#define GHST_ADDR_5G_TXCTRL 0x84 // phase 3 +#define GHST_ADDR_5G_TWRSCAN 0x85 +#define GHST_ADDR_5G_RLY 0x86 + +#define GHST_UL_RC_CHANS_HS4_5TO8 0x10 // High Speed 4 channel (12 bits), plus CH5-8 (8 bits) +#define GHST_UL_RC_CHANS_HS4_9TO12 0x11 // High Speed 4 channel (12 bits), plus CH9-12 (8 bits) +#define GHST_UL_RC_CHANS_HS4_13TO16 0x12 // High Speed 4 channel (12 bits), plus CH13-16 (8 bits) +#define GHST_UL_RC_CHANS_SIZE 12 // 1 (type) + 10 (data) + 1 (crc) + +#define GHST_DL_OPENTX_SYNC 0x20 +#define GHST_DL_LINK_STAT 0x21 +#define GHST_DL_VTX_STAT 0x22 + +#define GHST_RC_CTR_VAL_12BIT 0x7C0 // 0x3e0 << 1 +#define GHST_RC_CTR_VAL_8BIT 0x7C + +#define GHST_CH_BITS_12 12 +#define GHST_CH_BITS_8 8 + +enum GhstPowerMode +{ + GHST_PWR_16UW = 0, + GHST_PWR_100UW = 1, + GHST_PWR_1MW = 2, + GHST_PWR_25MW = 3, + GHST_PWR_100MW = 4, + GHST_PWR_200MW = 5, + GHST_PWR_350MW = 6, + GHST_PWR_500MW = 7, + GHST_PWR_600MW = 8, + GHST_PWR_1W = 9, + GHST_PWR_1_5W = 10, + GHST_PWR_2W = 11, + GHST_PWR_3W = 12, + GHST_PWR_4W = 13, + GHST_PWR_COUNT +}; + +enum GhstRFProfile +{ + GHST_RF_PROFILE_Auto = 0, + GHST_RF_PROFILE_Normal = 1, + GHST_RF_PROFILE_Race = 2, + GHST_RF_PROFILE_PureRace = 3, + GHST_RF_PROFILE_LongRange = 4, + GHST_RF_PROFILE_Reserved = 5, + GHST_RF_PROFILE_Race2 = 6, + GHST_RF_PROFILE_PureRace2 = 7, + GHST_RF_PROFILE_MAX = GHST_RF_PROFILE_PureRace2, + GHST_RF_PROFILE_COUNT +}; + +enum GhstVtxBand +{ + GHST_VTX_BAND_Unknown = 0, + GHST_VTX_BAND_Irc = 1, + GHST_VTX_BAND_Race = 2, + GHST_VTX_BAND_BandE = 3, + GHST_VTX_BAND_BandB = 4, + GHST_VTX_BAND_BandA = 5, + GHST_VTX_BAND_MAX = GHST_VTX_BAND_BandA, + GHST_VTX_BAND_COUNT +}; + +void processGhostTelemetryData(uint8_t data); +void ghostSetDefault(int index, uint8_t id, uint8_t subId); + +#if SPORT_MAX_BAUDRATE < 400000 +// For radios which can't support telemetry at high rates, offer baud rate choices +// (modified vs. unmodified radios) + +constexpr uint16_t BRR_400K = PERI1_FREQUENCY / 400000; +constexpr uint16_t BRR_115K = PERI1_FREQUENCY / 115200; + +enum GhostTelemetryBaudrates +{ + GHST_TELEMETRY_RATE_400K, + GHST_TELEMETRY_RATE_115K +}; +#endif +#define GHOST_BAUDRATE 400000 +#define GHOST_PERIOD 4 + +#endif // _GHOST_H_ diff --git a/radio/src/telemetry/hott.cpp b/radio/src/telemetry/hott.cpp index 8806094e8..6d7020f40 100644 --- a/radio/src/telemetry/hott.cpp +++ b/radio/src/telemetry/hott.cpp @@ -411,22 +411,22 @@ void processHottPacket(const uint8_t * packet) sensor = getHottSensor(HOTT_ID_CELS); // packet[7 ] uint8_t cell1_L; //#07 cell 1 voltage lower value. 0.02V steps, 124=2.48V value = packet[7] << 1; - if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision); + if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_GAM, 0 << 16 | value, sensor->unit, sensor->precision); // packet[8 ] uint8_t cell2_L; //#08 value = packet[8] << 1; - if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision); + if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_GAM, 1 << 16 | value, sensor->unit, sensor->precision); // packet[9 ] uint8_t cell3_L; //#09 value = packet[9] << 1; - if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision); + if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_GAM, 2 << 16 | value, sensor->unit, sensor->precision); // packet[10] uint8_t cell4_L; //#10 value = packet[10] << 1; - if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision); + if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_GAM, 3 << 16 | value, sensor->unit, sensor->precision); // packet[11] uint8_t cell5_L; //#11 value = packet[11] << 1; - if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision); + if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_GAM, 4 << 16 | value, sensor->unit, sensor->precision); // packet[12] uint8_t cell6_L; //#12 value = packet[12] << 1; - if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision); + if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_GAM, 5 << 16 | value, sensor->unit, sensor->precision); // packet[13] uint8_t batt1_L; //#13 battery 1 voltage LSB value. 0.1V steps. 50 = 5.5V break; diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 0e880e1a0..c26bbfece 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -21,7 +21,7 @@ #include "telemetry.h" #include "multi.h" -constexpr int32_t MULTI_DESIRED_VERSION = (1 << 24) | (3 << 16) | (1 << 8) | 1; +constexpr int32_t MULTI_DESIRED_VERSION = (1 << 24) | (3 << 16) | (1 << 8) | 69; #define MULTI_CHAN_BITS 11 extern uint8_t g_moduleIdx; @@ -319,13 +319,13 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) #if defined(AUX_SERIAL) if (g_eeGeneral.auxSerialMode == UART_MODE_TELEMETRY_MIRROR) { - for (uint8_t c=0; c < len; c++) + for (uint8_t c = 0; c < len + 2; c++) auxSerialPutc(packet[c]); } #endif #if defined(AUX2_SERIAL) if (g_eeGeneral.aux2SerialMode == UART_MODE_TELEMETRY_MIRROR) { - for (uint8_t c=0; c < len; c++) + for (uint8_t c = 0; c < len + 2; c++) aux2SerialPutc(packet[c]); } #endif diff --git a/radio/src/telemetry/spektrum.cpp b/radio/src/telemetry/spektrum.cpp index 8e2791540..b3cda5845 100644 --- a/radio/src/telemetry/spektrum.cpp +++ b/radio/src/telemetry/spektrum.cpp @@ -47,6 +47,7 @@ #define DSM_BIND_PACKET_LENGTH 12 #define I2C_HIGH_CURRENT 0x03 +#define I2C_FWD_PGM 0x09 #define I2C_TEXTGEN 0x0c #define I2C_GPS 0x17 #define I2C_GPS2 0x17 @@ -349,6 +350,20 @@ void processSpektrumPacket(const uint8_t *packet) // highest bit indicates that TM1100 is in use, ignore it uint8_t i2cAddress = (packet[2] & 0x7f); + if (i2cAddress == I2C_FWD_PGM) { +#if defined(LUA) + // Forward Programming + if (Multi_Buffer && memcmp(Multi_Buffer, "DSM", 3) == 0) { + // Multi_Buffer[0..2]=="DSM" -> Lua script is running + // Multi_Buffer[3]==0x70 -> 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 + Multi_Buffer[10] = i2cAddress; + memcpy(&Multi_Buffer[11], &packet[3], 15); // Store the received RX answer in the buffer + } +#endif + return; // Not a sensor + } //SmartBat Hack if (i2cAddress == I2C_SMART_BAT_BASE_ADDRESS) { i2cAddress = i2cAddress + (packet[4] >> 4); // use type to create virtual I2CAddresses @@ -468,17 +483,17 @@ void processSpektrumPacket(const uint8_t *packet) // "I" here means the multi module /* -0-3 4 bytes -> Cyrf ID of the TX xor 0xFF but you don't care as I've checked it already... -4 1 byte -> RX version but you don't care... +0-3 4 bytes -> Cyrf ID of the TX xor 0xFF but don't care... +4 1 byte -> RX version but don't care... 5 1 byte -> number of channels, example 0x06=6 channels 6 1 byte -> max DSM type allowed: - 0x01 => 22ms 1024 DSM2 1 packet => number of channels is <8 and no telemetry - 0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7 or telemetry enable RX - 0x12 => 11ms 2048 DSM2 2 packets => can be any number of channels with/without telemetry -> this mode might be supported following Mike's trials, note the channels should be duplicated between the packets which is not the case today - 0xa2 => 22ms 2048 DSMX 1 packet => number of channels is <8 and no telemetry - 0xb2 => 11ms 2048 DSMX => can be any number of channels with/without telemetry -> this mode is only half supported since the channels should be duplicated between the packets which is not the case but might be supported following Mike's trials + 0x01 => 1024 DSM2 1 packet => number of channels is <8 and no telemetry + 0x02 => 1024 DSM2 2 packets => either a number of channel >7 or telemetry enable RX + 0x12 => 2048 DSM2 2 packets => can be any number of channels with/without telemetry -> this mode might be supported following Mike's trials, note the channels should be duplicated between the packets which is not the case today + 0xa2 => 2048 DSMX 1 packet => number of channels is <8 and no telemetry + 0xb2 => 2048 DSMX 2 packets => can be any number of channels with/without telemetry -> this mode is only half supported since the channels should be duplicated between the packets which is not the case but might be supported following Mike's trials 7 0x00: not sure of the use of this byte since I've always seen it at 0... -8-9 2 bytes CRC but you don't care as I've checked it already... +8-9 2 bytes CRC but don't care... Examples: DSM #Chan RXver Inductrix 0xa2 07 1 @@ -488,22 +503,40 @@ void processSpektrumPacket(const uint8_t *packet) void processDSMBindPacket(uint8_t module, const uint8_t *packet) { uint32_t debugval; - if (g_model.moduleData[module].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2 - && g_model.moduleData[module].multi.autoBindMode) { - + if (g_model.moduleData[module].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2 && g_model.moduleData[module].subType == MM_RF_DSM2_SUBTYPE_AUTO) { + // Only sets channel etc when in DSM/AUTO mode int channels = packet[5]; - // Only sets channel etc when in DSM multi mode - g_model.moduleData[module].channelsCount = channels - 8; + if (channels > 12) { + channels = 12; + } + else if (channels < 3) { + channels = 3; + } - // bool use11ms = (packet[8] & 0x10) ; - if (packet[6] >= 0xb2) - g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_11; - else if (packet[6] >= 0xa2) - g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_22; - else if (packet[6] >= 0x12) - g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_11; - else - g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_22; + switch(packet[6]) { + case 0xa2: + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_22; + break; + case 0x12: + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_11; + if (channels == 7) { + channels = 12; // change the number of channels if 7 + } + break; + case 0x01: + case 0x02: + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_22; + break; + default: // 0xb2 or unknown + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_11; + if (channels == 7) { + channels = 12; // change the number of channels if 7 + } + break; + } + + g_model.moduleData[module].channelsCount = channels - 8; + g_model.moduleData[module].multi.optionValue &= 0xFD; // clear the 11ms servo refresh rate flag storageDirty(EE_MODEL); } diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 9da862a54..52799763e 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "multi.h" +#include "pulses/afhds3.h" uint8_t telemetryStreaming = 0; uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) @@ -44,6 +45,13 @@ void processTelemetryData(uint8_t data) } #endif +#if defined(GHOST) + if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) { + processGhostTelemetryData(data); + return; + } +#endif + #if defined(MULTIMODULE) if (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM) { processSpektrumTelemetryData(EXTERNAL_MODULE, data, telemetryRxBuffer, telemetryRxBufferCount); @@ -59,6 +67,13 @@ void processTelemetryData(uint8_t data) } #endif +#if defined(AFHDS3) + if (telemetryProtocol == PROTOCOL_TELEMETRY_AFHDS3) { + afhds3::processTelemetryData(EXTERNAL_MODULE, data, telemetryRxBuffer, telemetryRxBufferCount, TELEMETRY_RX_PACKET_SIZE); + return; + } +#endif + processFrskyTelemetryData(data); } @@ -103,7 +118,7 @@ void telemetryWakeup() #endif #if defined(EXTMODULE_USART) - while (extmoduleFifo.getFrame(frame)) { + while (isModulePXX2(EXTERNAL_MODULE) && extmoduleFifo.getFrame(frame)) { processPXX2Frame(EXTERNAL_MODULE, frame); } #endif @@ -199,6 +214,11 @@ void telemetryWakeup() if (TELEMETRY_STREAMING()) { if (telemetryState == TELEMETRY_KO) { AUDIO_TELEMETRY_BACK(); +#if defined(CROSSFIRE) + if (isModuleCrossfire(EXTERNAL_MODULE)) { + moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID; + } +#endif } telemetryState = TELEMETRY_OK; } @@ -285,6 +305,16 @@ void telemetryInit(uint8_t protocol) } #endif +#if defined(GHOST) + else if (protocol == PROTOCOL_TELEMETRY_GHOST) { + telemetryPortInit(GHOST_BAUDRATE, TELEMETRY_SERIAL_DEFAULT); +#if defined(LUA) + outputTelemetryBuffer.reset(); +#endif + telemetryPortSetDirectionOutput(); + } +#endif + #if defined(AUX_SERIAL) || defined(PCBSKY9X) else if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) { telemetryPortInit(0, TELEMETRY_SERIAL_DEFAULT); @@ -292,6 +322,13 @@ void telemetryInit(uint8_t protocol) } #endif +#if defined(AFHDS3) && !defined(SIMU) + else if (protocol == PROTOCOL_TELEMETRY_AFHDS3) { + telemetryPortInvertedInit(AFHDS3_BAUDRATE); + telemetryPortSetDirectionInput(); + } +#endif + else { telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_WITHOUT_DMA); #if defined(LUA) diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 1de358705..bafb0dc07 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -26,15 +26,19 @@ #include "crossfire.h" #include "myeeprom.h" #include "io/frsky_sport.h" - +#if defined(GHOST) + #include "ghost.h" +#endif #if defined(MULTIMODULE) #include "spektrum.h" - #include "flysky_ibus.h" #include "hitec.h" #include "hott.h" #include "multi.h" #endif #include "myeeprom.h" +#if defined(MULTIMODULE) || defined(AFHDS3) + #include "flysky_ibus.h" +#endif extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time @@ -56,7 +60,7 @@ constexpr uint8_t TELEMETRY_TIMEOUT10ms = 100; // 1 second #define TELEMETRY_SERIAL_8E2 1 #define TELEMETRY_SERIAL_WITHOUT_DMA 2 -#if defined(CROSSFIRE) || defined(MULTIMODULE) +#if defined(CROSSFIRE) || defined(MULTIMODULE) || defined(AFHDS3) #define TELEMETRY_RX_PACKET_SIZE 128 // multi module Spektrum telemetry is 18 bytes, FlySky is 37 bytes #else @@ -95,6 +99,7 @@ PACK(struct CellValue }); int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, int32_t value, uint32_t unit, uint32_t prec); +int setTelemetryText(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, const char * text); void delTelemetryIndex(uint8_t index); int availableTelemetryIndex(); int lastUsedTelemetryIndex(); @@ -112,17 +117,21 @@ extern uint8_t telemetryProtocol; #if defined (MULTIMODULE) #define IS_D16_MULTI(module) (((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) && (g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16 || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_CLONED)) \ || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX2)) + #define IS_R9_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY_R9) #define IS_HOTT_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT) + #define IS_DSM_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) #define IS_RX_MULTI(module) ((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_AFHDS2A_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX_RX) \ || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_BAYANG_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM_RX)) #if defined(HARDWARE_INTERNAL_MODULE) - #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(INTERNAL_MODULE)||IS_D16_MULTI(EXTERNAL_MODULE)))) + #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(INTERNAL_MODULE) || IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(INTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE)))) #else - #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && IS_D16_MULTI(EXTERNAL_MODULE))) + #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE)))) #endif #else #define IS_D16_MULTI(module) false + #define IS_R9_MULTI(module) false #define IS_HOTT_MULTI(module) false + #define IS_DSM_MULTI(module) false #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) #define IS_RX_MULTI(module) false #endif @@ -151,6 +160,12 @@ inline uint8_t modelTelemetryProtocol() } #endif +#if defined(GHOST) + if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST) { + return PROTOCOL_TELEMETRY_GHOST; + } +#endif + if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) { return g_model.telemetryProtocol; } @@ -164,6 +179,11 @@ inline uint8_t modelTelemetryProtocol() return PROTOCOL_TELEMETRY_MULTIMODULE; } #endif +#endif +#if defined(AFHDS3) + if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_AFHDS3) { + return PROTOCOL_TELEMETRY_AFHDS3; + } #endif // default choice return PROTOCOL_TELEMETRY_FRSKY_SPORT; diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp index 0896e1424..398c15961 100644 --- a/radio/src/telemetry/telemetry_sensors.cpp +++ b/radio/src/telemetry/telemetry_sensors.cpp @@ -78,21 +78,27 @@ uint32_t getDistFromEarthAxis(int32_t latitude) return 139*(((uint32_t)10000000 - ((angle2*(uint32_t)123370)/81) + (angle4/25))/12500); } +void TelemetryItem::setValue(const TelemetrySensor & sensor, const char * val, uint32_t, uint32_t) +{ + strncpy(text, val, sizeof(text)); + setFresh(); +} + void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32_t unit, uint32_t prec) { int32_t newVal = val; - if(prec == 255) { + if (prec == 255) { prec = sensor.prec; } if (unit == UNIT_CELLS) { - uint32_t data = uint32_t(newVal); - uint8_t cellsCount = (data >> 24); - uint8_t cellIndex = ((data >> 16) & 0x0F); + auto data = uint32_t(newVal); + uint8_t cellsCount = (data >> 24u); + uint8_t cellIndex = ((data >> 16u) & 0x0Fu); if (cellIndex >= MAX_CELLS) return; - uint16_t cellValue = (data & 0xFFFF); + uint16_t cellValue = (data & 0xFFFFu); if (cellsCount == 0) { cellsCount = (cellIndex >= cells.count ? cellIndex + 1 : cells.count); if (cellsCount != cells.count) { @@ -178,18 +184,18 @@ void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32 } else if (unit == UNIT_DATETIME_DAY_MONTH) { auto data = uint32_t(newVal); - datetime.month = data >> 8; - datetime.day = data & 0xFF; + datetime.month = data >> 8u; + datetime.day = data & 0xFFu; return; } else if (unit == UNIT_DATETIME_HOUR_MIN) { auto data = uint32_t(newVal); - datetime.hour = (data & 0xFF); - datetime.min = data >> 8; + datetime.hour = (data & 0xFFu); + datetime.min = data >> 8u; return; } else if (unit == UNIT_DATETIME_SEC) { - datetime.sec = newVal & 0xFF; + datetime.sec = newVal & 0xFFu; newVal = 0; } else if (unit == UNIT_RPMS) { @@ -198,8 +204,6 @@ void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32 } } else if (unit == UNIT_TEXT) { - *((uint32_t*)&text[prec]) = newVal; - setFresh(); return; } else { @@ -380,7 +384,7 @@ void TelemetryItem::eval(const TelemetrySensor & sensor) result = isqrt32(result); if (altItem) { - dist = abs(altItem->value) / g_model.telemetrySensors[sensor.dist.alt-1].getPrecDivisor(); + dist = convertTelemetryValue(abs(altItem->value), g_model.telemetrySensors[sensor.dist.alt-1].unit, g_model.telemetrySensors[sensor.dist.alt-1].prec, UNIT_METERS, 0); result = (dist * dist) + (result * result); result = isqrt32(result); } @@ -495,7 +499,8 @@ int lastUsedTelemetryIndex() return -1; } -int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, int32_t value, uint32_t unit, uint32_t prec) +template +int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, T value, uint32_t unit = 0, uint32_t prec = 0) { bool sensorFound = false; @@ -518,34 +523,50 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui case PROTOCOL_TELEMETRY_FRSKY_SPORT: frskySportSetDefault(index, id, subId, instance); break; + case PROTOCOL_TELEMETRY_FRSKY_D: frskyDSetDefault(index, id); break; + #if defined(CROSSFIRE) case PROTOCOL_TELEMETRY_CROSSFIRE: crossfireSetDefault(index, id, instance); break; #endif + +#if defined(GHOST) + case PROTOCOL_TELEMETRY_GHOST: + ghostSetDefault(index, id, instance); + break; +#endif + +#if defined(MULTIMODULE) || defined(AFHDS3) + case PROTOCOL_TELEMETRY_FLYSKY_IBUS: + flySkySetDefault(index,id, subId, instance); + break; +#endif + #if defined(MULTIMODULE) case PROTOCOL_TELEMETRY_SPEKTRUM: spektrumSetDefault(index, id, subId, instance); break; - case PROTOCOL_TELEMETRY_FLYSKY_IBUS: - flySkySetDefault(index,id, subId, instance); - break; + case PROTOCOL_TELEMETRY_HITEC: hitecSetDefault(index, id, subId, instance); break; + case PROTOCOL_TELEMETRY_HOTT: hottSetDefault(index, id, subId, instance); break; #endif + #if defined(LUA) case PROTOCOL_TELEMETRY_LUA: // Sensor will be initialized by calling function // This drops the first value return index; #endif + default: return index; } @@ -556,7 +577,16 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui POPUP_WARNING(STR_TELEMETRYFULL); return -1; } +} +int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, int32_t value, uint32_t unit, uint32_t prec) +{ + return setTelemetryValue(protocol, id, subId, instance, value, unit, prec); +} + +int setTelemetryText(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, const char * text) +{ + return setTelemetryValue(protocol, id, subId, instance, text); } void TelemetrySensor::init(const char * label, uint8_t unit, uint8_t prec) @@ -598,6 +628,7 @@ PACK(typedef struct { const UnitConversionRule unitConversionTable[] = { /* unitFrom unitTo multiplier divisor */ { UNIT_METERS, UNIT_FEET, 105, 32}, + { UNIT_FEET, UNIT_METERS, 32, 105}, { UNIT_METERS_PER_SECOND, UNIT_FEET_PER_SECOND, 105, 32}, { UNIT_KTS, UNIT_KMH, 1852, 1000}, // 1 knot = 1.85200 kilometers per hour @@ -732,9 +763,9 @@ bool TelemetrySensor::isSameInstance(TelemetryProtocol protocol, uint8_t instanc return true; #else if (((this->instance ^ instance) & 0x9F) == 0 && (this->instance >> 5) != TELEMETRY_ENDPOINT_SPORT && (instance >> 5) != TELEMETRY_ENDPOINT_SPORT) { - this->instance = instance; // update the instance in case we had telemetry switching - return true; - } + this->instance = instance; // update the instance in case we had telemetry switching + return true; + } #endif } diff --git a/radio/src/telemetry/telemetry_sensors.h b/radio/src/telemetry/telemetry_sensors.h index 6ca1c0c97..e2fbcd498 100644 --- a/radio/src/telemetry/telemetry_sensors.h +++ b/radio/src/telemetry/telemetry_sensors.h @@ -91,6 +91,8 @@ class TelemetryItem void eval(const TelemetrySensor & sensor); void per10ms(const TelemetrySensor & sensor); + void setValue(const TelemetrySensor & sensor, const char * newVal, uint32_t unit=UNIT_TEXT, uint32_t prec=0); + void setValue(const TelemetrySensor & sensor, int32_t newVal, uint32_t unit, uint32_t prec=0); inline bool isAvailable() diff --git a/radio/src/tests/mixer.cpp b/radio/src/tests/mixer.cpp index 44ab6fdaf..2ef2d95be 100644 --- a/radio/src/tests/mixer.cpp +++ b/radio/src/tests/mixer.cpp @@ -720,3 +720,152 @@ TEST_F(MixerTest, flightModeOverflow) simuSetSwitch(0, 1); CHECK_FLIGHT_MODE_TRANSITION(0, 1000, 1024, 1024); } + +TEST_F(TrimsTest, throttleTrimWithCrossTrims) +{ + g_model.thrTrim = 1; + g_model.thrTrimSw = MIXSRC_TrimEle - MIXSRC_FIRST_TRIM; + ExpoData *expo = expoAddress(THR_STICK); + expo->carryTrim = TRIM_ELE; + expo = expoAddress(ELE_STICK); + expo->carryTrim = TRIM_THR; + + // stick max + trim max + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], 1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick max + trim min + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], 1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim max + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024 + 500); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim mid + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, 0); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024 + 250); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim min + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024); + EXPECT_EQ(channelOutputs[1], 0); + + // now the same tests with extended Trims + g_model.extendedTrims = 1; + // stick max + trim max + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], 1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick max + trim min + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], 1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim max + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024+2000); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim mid + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, 0); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024+1000); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim min + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024); + EXPECT_EQ(channelOutputs[1], 0); +} + +TEST_F(TrimsTest, invertedThrottlePlusThrottleTrimWithCrossTrims) +{ + g_model.throttleReversed = 1; + g_model.thrTrim = 1; + g_model.thrTrimSw = MIXSRC_TrimEle - MIXSRC_FIRST_TRIM; + ExpoData *expo = expoAddress(THR_STICK); + expo->carryTrim = TRIM_ELE; + expo = expoAddress(ELE_STICK); + expo->carryTrim = TRIM_THR; + + // stick max + trim max + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick max + trim mid + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, 0); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024+250); + EXPECT_EQ(channelOutputs[1], 0); + // stick max + trim min + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024+500); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim max + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], +1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim min + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], +1024); + EXPECT_EQ(channelOutputs[1], 0); + + // now the same tests with extended Trims + g_model.extendedTrims = 1; + // stick max + trim max + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick max + trim mid + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, 0); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024+1000); + EXPECT_EQ(channelOutputs[1], 0); + // stick max + trim min + anaInValues[THR_STICK] = +1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], -1024+2000); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim max + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MAX); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], +1024); + EXPECT_EQ(channelOutputs[1], 0); + // stick min + trim min + anaInValues[THR_STICK] = -1024; + setTrimValue(0, MIXSRC_TrimEle - MIXSRC_FIRST_TRIM, TRIM_EXTENDED_MIN); + evalMixes(1); + EXPECT_EQ(channelOutputs[2], +1024); + EXPECT_EQ(channelOutputs[1], 0); +} diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 7708ed507..cdc50ad92 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 7708ed5076b5fcf13e030d160d0fc0fafd1a6b5a +Subproject commit cdc50ad92d65ef7e6174737a80a111e9fd884ea5 diff --git a/radio/src/trainer.cpp b/radio/src/trainer.cpp index e434b307b..5754d20a7 100644 --- a/radio/src/trainer.cpp +++ b/radio/src/trainer.cpp @@ -115,9 +115,16 @@ void checkTrainerSettings() #if defined(HARDWARE_TRAINER_AUX_SERIAL) case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: +#if defined(AUX_SERIAL) if (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) auxSerialSbusInit(); else +#endif +#if defined(AUX2_SERIAL) + if (g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER) + aux2SerialSbusInit(); + else +#endif init_trainer_capture(); break; #endif diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 1cdcdb28c..e4b996f35 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -70,6 +70,8 @@ ISTR(XJT_ACCST_RF_PROTOCOLS); ISTR(ISRM_RF_PROTOCOLS); ISTR(R9M_PXX2_RF_PROTOCOLS); ISTR(DSM_PROTOCOLS); +ISTR(AFHDS3_PROTOCOLS); +ISTR(AFHDS3_POWERS); ISTR(CURVE_TYPES); ISTR(VSENSORTYPES); ISTR(VFORMULAS); @@ -98,6 +100,7 @@ ISTR(INPUTNAMES); #if defined(MULTIMODULE) ISTR(MULTI_PROTOCOLS); +ISTR(MULTI_POWER); #endif #if defined(BLUETOOTH) @@ -125,6 +128,7 @@ const char STR_TRIMINC[] = TR_TRIMINC; const char STR_DISPLAY_TRIMS[] = TR_DISPLAY_TRIMS; const char STR_TTRACE[] = TR_TTRACE; const char STR_TTRIM[] = TR_TTRIM; +const char STR_TTRIM_SW[] = TR_TTRIM_SW; const char STR_BEEPCTR[] = TR_BEEPCTR; const char STR_USE_GLOBAL_FUNCS[] = TR_USE_GLOBAL_FUNCS; const char STR_PPMFRAME[] = TR_PPMFRAME; @@ -364,6 +368,7 @@ const char STR_SPECTRUM_ANALYSER_EXT[] = TR_SPECTRUM_ANALYSER_EXT; const char STR_SPECTRUM_ANALYSER_INT[] = TR_SPECTRUM_ANALYSER_INT; const char STR_WAITING_FOR_RX[] = TR_WAITING_FOR_RX; const char STR_WAITING_FOR_TX[] = TR_WAITING_FOR_TX; +const char STR_WARN_5VOLTS[] = TR_WARN_5VOLTS; const char STR_CAT_NOT_EMPTY[] = TR_CAT_NOT_EMPTY; const char STR_WARNING[] = TR_WARNING; const char STR_THROTTLE_WARNING[] = TR_THROTTLE_WARNING; @@ -445,8 +450,10 @@ const char STR_FIRMWARE_UPDATE_SUCCESS[] = TR_FIRMWARE_UPDATE_SUCCESS; const char STR_WRITING[] = TR_WRITING; const char STR_FLASH_EXTERNAL_DEVICE[] = TR_FLASH_EXTERNAL_DEVICE; const char STR_FLASH_RECEIVER_OTA[] = TR_FLASH_RECEIVER_OTA; -const char STR_FLASH_RECEIVER_OTA_BY_EXTERNAL[] = TR_FLASH_RECEIVER_OTA_BY_EXTERNAL; -const char STR_FLASH_RECEIVER_OTA_BY_INTERNAL[] = TR_FLASH_RECEIVER_OTA_BY_INTERNAL; +const char STR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA[] = TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA; +const char STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA[] = TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA; +const char STR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA[] = TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA; +const char STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA[] = TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA; const char STR_FLASH_BLUETOOTH_MODULE[] = TR_FLASH_BLUETOOTH_MODULE; const char STR_FLASH_POWER_MANAGEMENT_UNIT[] = TR_FLASH_POWER_MANAGEMENT_UNIT; const char STR_CONFIRM_FORMAT[] = TR_CONFIRM_FORMAT; @@ -640,6 +647,9 @@ const char STR_LAYOUT[] = TR_LAYOUT; const char STR_ADD_MAIN_VIEW[] = TR_ADD_MAIN_VIEW; const char STR_BACKGROUND_COLOR[] = TR_BACKGROUND_COLOR; const char STR_MAIN_COLOR[] = TR_MAIN_COLOR; +const char STR_BAR2_COLOR[] = TR_BAR2_COLOR; +const char STR_BAR1_COLOR[] = TR_BAR1_COLOR; +const char STR_TEXT_COLOR[] = TR_TEXT_COLOR; const char STR_TEXT_VIEWER[] = TR_TEXT_VIEWER; const char STR_RF_POWER[] = TR_RF_POWER; const char STR_BYTES[] = TR_BYTES; @@ -764,6 +774,7 @@ const char STR_GYRO_MAX[] = TR_GYRO_MAX; #if defined(PWM_BACKLIGHT) || defined(COLORLCD) const char STR_BLONBRIGHTNESS[] = TR_BLONBRIGHTNESS; const char STR_BLOFFBRIGHTNESS[] = TR_BLOFFBRIGHTNESS; +const char STR_KEYS_BACKLIGHT[] = TR_KEYS_BACKLIGHT; #endif const char STR_TIMEZONE[] = TR_TIMEZONE; @@ -805,6 +816,7 @@ const char STR_BIND_OK[] = TR_BIND_OK; const char STR_MULTI_CUSTOM[] = TR_MULTI_CUSTOM; const char STR_MULTI_RFTUNE[] = TR_MULTI_RFTUNE; +const char STR_MULTI_RFPOWER[] = TR_MULTI_RFPOWER; const char STR_MULTI_TELEMETRY[] = TR_MULTI_TELEMETRY; const char STR_MULTI_VIDFREQ[] = TR_MULTI_VIDFREQ; const char STR_MULTI_OPTION[] = TR_MULTI_OPTION; @@ -829,8 +841,16 @@ const char STR_MULTI_SERVOFREQ[] = TR_MULTI_SERVOFREQ; const char STR_MULTI_MAX_THROW[] = TR_MULTI_MAX_THROW; const char STR_MULTI_RFCHAN[] = TR_MULTI_RFCHAN; const char STR_NEEDS_FILE[] = TR_NEEDS_FILE; -const char STR_EXT_MULTI_SPEC[] = TR_EXT_MULTI_SPEC; -const char STR_INT_MULTI_SPEC[] = TR_INT_MULTI_SPEC; +const char STR_EXT_MULTI_SPEC[] = TR_EXT_MULTI_SPEC; +const char STR_INT_MULTI_SPEC[] = TR_INT_MULTI_SPEC; + +#if defined(AFHDS3) +const char STR_AFHDS3_RX_FREQ[] = TR_AFHDS3_RX_FREQ; +const char STR_AFHDS3_ACTUAL_POWER[] = TR_AFHDS3_ACTUAL_POWER; +const char STR_AFHDS3_POWER_SOURCE[] = TR_AFHDS3_POWER_SOURCE; +const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[] =TR_AFHDS3_ONE_TO_ONE_TELEMETRY; +const char STR_AFHDS3_ONE_TO_MANY[] = TR_AFHDS3_ONE_TO_MANY; +#endif #if LCD_W < 212 const char STR_SUBTYPE[] = TR_SUBTYPE; diff --git a/radio/src/translations.h b/radio/src/translations.h index 787143aba..933b8cf5b 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -126,10 +126,7 @@ extern const char STR_FUNCSOUNDS[]; extern const char STR_VTELEMUNIT[]; extern const char STR_GPSFORMAT[]; extern const char STR_VTELEMSCREENTYPE[]; - -#if defined(HELI) extern const char STR_VSWASHTYPE[]; -#endif extern const char STR_VKEYS[]; extern const char STR_VSWITCHES[]; @@ -166,13 +163,19 @@ extern const char STR_XJT_ACCST_RF_PROTOCOLS[]; extern const char STR_ISRM_RF_PROTOCOLS[]; extern const char STR_R9M_PXX2_RF_PROTOCOLS[]; extern const char STR_DSM_PROTOCOLS[]; -extern const char STR_FLYSKY_PROTOCOLS[]; extern const char STR_CRSF_BAUDRATE[]; extern const char STR_PPM_POL[]; -#if defined(MULTIMODULE) extern const char STR_MULTI_PROTOCOLS[]; -#endif +extern const char STR_MULTI_POWER[]; + +extern const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[]; +extern const char STR_AFHDS3_ONE_TO_MANY[]; +extern const char STR_AFHDS3_PROTOCOLS[]; +extern const char STR_AFHDS3_POWERS[]; +extern const char STR_AFHDS3_RX_FREQ[]; +extern const char STR_AFHDS3_ACTUAL_POWER[]; +extern const char STR_AFHDS3_POWER_SOURCE[]; extern const char STR_CURVE_TYPES[]; extern const char STR_VSENSORTYPES[]; @@ -181,7 +184,6 @@ extern const char STR_VPREC[]; extern const char STR_VCELLINDEX[]; extern const char STR_TOUCH_PANEL[]; -#if defined(BLUETOOTH) extern const char STR_BLUETOOTH[]; extern const char STR_BLUETOOTH_DISC[]; extern const char STR_BLUETOOTH_INIT[]; @@ -189,9 +191,8 @@ extern const char STR_BLUETOOTH_DIST_ADDR[]; extern const char STR_BLUETOOTH_LOCAL_ADDR[]; extern const char STR_BLUETOOTH_PIN_CODE[]; extern const char STR_BLUETOOTH_MODES[]; -#endif -#define NO_INDENT(x) (x)+LEN_INDENT +#define NO_INDENT(x) (x) + LEN_INDENT extern const char STR_POPUPS_ENTER_EXIT[]; extern const char STR_OK[]; @@ -218,6 +219,7 @@ extern const char STR_TRIMINC[]; extern const char STR_DISPLAY_TRIMS[]; extern const char STR_TTRACE[]; extern const char STR_TTRIM[]; +extern const char STR_TTRIM_SW[]; extern const char STR_BEEPCTR[]; extern const char STR_USE_GLOBAL_FUNCS[]; @@ -308,6 +310,7 @@ extern const char STR_BACKLIGHT_LABEL[]; #if defined(PWM_BACKLIGHT) || defined(COLORLCD) extern const char STR_BLONBRIGHTNESS[]; extern const char STR_BLOFFBRIGHTNESS[]; +extern const char STR_KEYS_BACKLIGHT[]; #endif extern const char STR_SPLASHSCREEN[]; @@ -405,6 +408,7 @@ extern const char STR_MULTI_FIXEDID[]; extern const char STR_MULTI_OPTION[]; extern const char STR_MULTI_VIDFREQ[]; extern const char STR_MULTI_RFTUNE[]; +extern const char STR_MULTI_RFPOWER[]; extern const char STR_MULTI_TELEMETRY[]; extern const char STR_MULTI_AUTOBIND[]; extern const char STR_DISABLE_CH_MAP[]; @@ -549,6 +553,7 @@ extern const char STR_SPECTRUM_ANALYSER_EXT[]; extern const char STR_SPECTRUM_ANALYSER_INT[]; extern const char STR_WAITING_FOR_RX[]; extern const char STR_WAITING_FOR_TX[]; +extern const char STR_WARN_5VOLTS[]; #if defined(SDCARD) extern const char STR_BACKUP_MODEL[]; @@ -668,8 +673,10 @@ extern const char STR_VIEW_TEXT[]; extern const char STR_FLASH_BOOTLOADER[]; extern const char STR_FLASH_EXTERNAL_DEVICE[]; extern const char STR_FLASH_RECEIVER_OTA[]; -extern const char STR_FLASH_RECEIVER_OTA_BY_EXTERNAL[]; -extern const char STR_FLASH_RECEIVER_OTA_BY_INTERNAL[]; +extern const char STR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA[]; +extern const char STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA[]; +extern const char STR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA[]; +extern const char STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA[]; extern const char STR_FLASH_BLUETOOTH_MODULE[]; extern const char STR_FLASH_POWER_MANAGEMENT_UNIT[]; extern const char STR_CURRENT_VERSION[]; @@ -949,6 +956,9 @@ extern const char STR_LAYOUT[]; extern const char STR_ADD_MAIN_VIEW[]; extern const char STR_BACKGROUND_COLOR[]; extern const char STR_MAIN_COLOR[]; +extern const char STR_BAR2_COLOR[]; +extern const char STR_BAR1_COLOR[]; +extern const char STR_TEXT_COLOR[]; extern const char STR_TEXT_VIEWER[]; extern const char STR_RF_POWER[]; diff --git a/radio/src/translations/cn.h.txt b/radio/src/translations/cn.h.txt index 0e0bf0967..03edbc53e 100644 --- a/radio/src/translations/cn.h.txt +++ b/radio/src/translations/cn.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Quiet""Alarm""NoKey""All\0 " -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE TR("\004", "\010") #define TR_VBLMODE TR("OFF\0""Keys""Ctrl""Both""ON\0 ", "OFF\0 ""Keys\0 ""Controls""Both\0 ""ON\0 ") @@ -71,8 +68,6 @@ #define TR_AUX_SERIAL_MODES "OFF\0 ""Telem Mirror\0""Telemetry In\0""SBUS Trainer\0""LUA\0 " #endif -#define TR_AUX2_SERIAL_MODE "Serial port 2" - #define LEN_SWTYPES "\006" #define TR_SWTYPES "None\0 ""Toggle""2POS\0 ""3POS\0" @@ -88,14 +83,14 @@ #define LEN_VPERSISTENT "\014" #define TR_VPERSISTENT "OFF\0 ""Flight\0 ""Manual Reset" -#define LEN_COUNTRY_CODES TR("\002", "\007") -#define TR_COUNTRY_CODES TR("US""JP""EU", "America""Japan\0 ""Europe\0") +#define LEN_COUNTRY_CODES TR("\002", "\007") +#define TR_COUNTRY_CODES TR("US""JP""EU", "America""Japan\0 ""Europe\0") #define LEN_USBMODES TR("\006", "\010") #define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ") -#define LEN_JACK_MODES "\007" -#define TR_JACK_MODES "Ask\0 ""Audio\0 ""Trainer" +#define LEN_JACK_MODES "\007" +#define TR_JACK_MODES "Ask\0 ""Audio\0 ""Trainer" #define LEN_TELEMETRY_PROTOCOLS "\017" #define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry" @@ -123,7 +118,7 @@ #define LEN_RETA123 "\001" #if defined(PCBHORUS) - #define TR_RETA123 "RETA12345LR" + #define TR_RETA123 "RETA13245LR" #elif defined(PCBX9E) #define TR_RETA123 "RETA1234LRLR" #elif defined(PCBTARANIS) || defined(REVX) @@ -271,7 +266,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -365,7 +360,7 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/SBUS Module" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") #define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" @@ -418,7 +413,6 @@ #if defined(PCBTARANIS) #define TR_POPUPS_ENTER_EXIT TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER) - #else #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT #endif @@ -442,7 +436,8 @@ #define TR_TRIMINC "Trim Step" #define TR_DISPLAY_TRIMS TR("Show Trims", "Display trims") #define TR_TTRACE TR("T-Source", INDENT "Source") -#define TR_TTRIM TR("T-Trim", INDENT "Trim idle only") +#define TR_TTRIM TR("T-Trim-Idle", INDENT "Trim idle only") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Ctr Beep", "Center Beep") #define TR_USE_GLOBAL_FUNCS TR("Glob.Funcs", "Use global funcs") #if defined(PCBSKY9X) && defined(REVX) @@ -452,6 +447,7 @@ #define TR_PPMFRAME INDENT "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH "Switch" @@ -489,10 +485,10 @@ #define TR_ANTENNA "Antenna" #define TR_NO_INFORMATION TR("No info", "No information") #define TR_MULTPX "Multiplex" -#define TR_DELAYDOWN "Delay dn" +#define TR_DELAYDOWN TR("Delay dn", "Delay down") #define TR_DELAYUP "Delay up" -#define TR_SLOWDOWN "Slow dn" -#define TR_SLOWUP "Slow up" +#define TR_SLOWDOWN TR("Slow dn", "Slow down") +#define TR_SLOWUP "Slow up" #define TR_MIXES "MIXES" #define TR_CV "CV" #if defined(PCBNV14) @@ -531,7 +527,6 @@ #define TR_MODEL_STILL_POWERED "模型未断电" #define TR_MODEL_SHUTDOWN "关机 ?" #define TR_PRESS_ENTER_TO_CONFIRM "按ENTER键确认" -#define TR_RENAVIG "RotEnc Navig" #define TR_THROTTLE_LABEL "油门" #define TR_THROTTLEREVERSE TR("T-Reverse", INDENT "Reverse") #define TR_MINUTEBEEP TR("分", "分钟播报") @@ -540,6 +535,7 @@ #define TR_BACKLIGHT_LABEL "背光" #define TR_BLONBRIGHTNESS "背光开" #define TR_BLOFFBRIGHTNESS "背光关" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "颜色" #define TR_SPLASHSCREEN "开机图片" #define TR_PWR_ON_DELAY "开机延迟" @@ -561,8 +557,6 @@ #define TR_MODESRC "Mode\006% Source" #define TR_MULTIPLIER "乘数" #define TR_CAL "Cal" -#define TR_TOUCH_NOTFOUND "Touch hardware not found" -#define TR_TOUCH_EXIT "Touch screen to exit" #define TR_CALIBRATION "校准" #define TR_VTRIM "Trim- +" #define TR_BG "BG:" @@ -587,7 +581,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER " to reset" @@ -649,6 +642,7 @@ #define TR_RECEIVER_NUM TR("RxNum", "Receiver No.") #define TR_RECEIVER "Receiver" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -683,6 +677,11 @@ #define TR_MULTI_SERVOFREQ TR("Servo rate", "Servo update rate") #define TR_MULTI_MAX_THROW TR("Max. Throw", "Enable max. throw") #define TR_MULTI_RFCHAN TR("RF Channel", "Select RF channel") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_SYNCMENU "[Sync]" #define TR_LIMIT INDENT "Limit" #define TR_MINRSSI "Min Rssi" @@ -762,9 +761,9 @@ #define TR_ALARMSWARN "ALARMS" #define TR_SWITCHWARN TR("SWITCH", "CONTROL") #define TR_FAILSAFEWARN "FAILSAFE" -#define TR_TEST_WARNING TR("NIGHTLY", "NIGHTLY BUILD") -#define TR_TEST_NOTSAFE "Version not safe to fly" -#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") +#define TR_TEST_WARNING TR("TESTING", "TEST BUILD") +#define TR_TEST_NOTSAFE "Use for tests only" +#define TR_WRONG_SDCARDVERSION TR("Expected ver: ", "Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" #define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" @@ -818,8 +817,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" @@ -852,8 +851,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE TR("Flash S.Port", "Flash S.Port device") #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Curr Vers: ", "Current version: ") @@ -866,8 +867,8 @@ #define TR_WRITING "Writing..." #define TR_CONFIRM_FORMAT "Confirm Format?" #define TR_INTERNALRF "Internal RF" -#define TR_INTERNAL_MODULE TR("Int. module","Internal module") -#define TR_EXTERNAL_MODULE TR("Ext. module","External module") +#define TR_INTERNAL_MODULE TR("Int. module", "Internal module") +#define TR_EXTERNAL_MODULE TR("Ext. module", "External module") #define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required" #define TR_TELEMETRY_DISABLED "Telem. disabled" #define TR_MORE_OPTIONS_AVAILABLE "More options available" @@ -928,9 +929,9 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND BUTTON(TR("Bnd", "Bind")) #define TR_POWERMETER_ATTN_NEEDED "Attenuator needed" -#define TR_PXX2_SELECT_RX "Select RX..." +#define TR_PXX2_SELECT_RX "Select RX" #define TR_PXX2_DEFAULT "" -#define TR_BT_SELECT_DEVICE "Select device..." +#define TR_BT_SELECT_DEVICE "Select device" #define TR_DISCOVER "Discover" #define TR_BUTTON_INIT BUTTON("Init") #define TR_WAITING "Waiting..." @@ -944,8 +945,10 @@ #define TR_DEL_BUTTON BUTTON(TR("Del", "Delete")) #define TR_RESET_BTN BUTTON("Reset") #define TR_DEBUG "Debug" -#define TR_KEYS_BTN BUTTON(TR("Keys", "Switches")) +#define TR_KEYS_BTN BUTTON("Keys") #define TR_ANALOGS_BTN BUTTON(TR("Anas", "Analogs")) +#define TR_TOUCH_NOTFOUND "Touch hardware not found" +#define TR_TOUCH_EXIT "Touch screen to exit" #define TR_SET BUTTON("Set") #define TR_TRAINER "Trainer" #define TR_CHANS "Chans" @@ -1014,6 +1017,7 @@ #define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Display checklist") #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS offset") #define TR_AUX_SERIAL_MODE "串口" +#define TR_AUX2_SERIAL_MODE "Serial port 2" #define TR_SCRIPT "脚本" #define TR_INPUTS "输入" #define TR_OUTPUTS "输出" @@ -1027,7 +1031,6 @@ #define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens" #define TR_TOUCH_PANEL "Touch panel:" - // Horus and Taranis column headers #define TR_PHASES_HEADERS_NAME "名称" #define TR_PHASES_HEADERS_SW "开关" @@ -1053,7 +1056,7 @@ #define TR_LSW_HEADERS_V1 "V1" #define TR_LSW_HEADERS_V2 "V2" #define TR_LSW_HEADERS_ANDSW "AND Switch" -#define TR_LSW_HEADERS_DURATION "Min Duration" +#define TR_LSW_HEADERS_DURATION "Duration" #define TR_LSW_HEADERS_DELAY "Delay" #define TR_GVAR_HEADERS_NAME "Name" @@ -1203,6 +1206,9 @@ #define TR_ADD_MAIN_VIEW "Add main view" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" #define TR_MENU_INPUTS "\214Inputs" #define TR_MENU_LUA "\222Lua scripts" @@ -1369,3 +1375,13 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 44e2938bf..cf33177ae 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -260,7 +260,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Metr.\0""Imper.", "Metrické""Imperial") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -434,6 +434,7 @@ #define TR_DISPLAY_TRIMS TR3("Číslo v Trm", "Zobr.hodnotu trimu", "Číslo v liště trimu") #define TR_TTRACE TR("StopaPlynu", INDENT "Stopa plynu") #define TR_TTRIM TR3("TrimVolnob.", INDENT "Trim jen volnoběh", "Trim jen pro volnoběh") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR3("Středy \221\222", "Pípat středy \221\222", "Pípat středy") #define TR_USE_GLOBAL_FUNCS TR("Glob.Funkce", "Použít Glob.Funkce") #if defined(PCBSKY9X) && defined(REVX) @@ -443,6 +444,7 @@ #define TR_PPMFRAME INDENT "PPM modulace" #define TR_REFRESHRATE TR(INDENT "Obnovit", INDENT "Obn. frekv.") #define STR_WARN_BATTVOLTAGE TR(INDENT "Výstup VBAT: ", INDENT "Varování: výstupní hodnota VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequence" #define TR_SWITCH "Spínač" @@ -530,6 +532,7 @@ #define TR_BACKLIGHT_LABEL "Podsvětlení" #define TR_BLONBRIGHTNESS TR3("Jas Zap.", "Jas Zap.", "Jas zapnutého LCD") #define TR_BLOFFBRIGHTNESS TR3("Jas Vyp.", "Jas Vyp.", "Jas vypnutého LCD") +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Barva" #define TR_SPLASHSCREEN TR("úvodní logo", "Zobrazit úvodní logo") #define TR_PWR_ON_DELAY "Pwr On delay" @@ -635,6 +638,7 @@ #define TR_RECEIVER_NUM TR("RX číslo", "Číslo přijímače") #define TR_RECEIVER "Přijímač" #define TR_MULTI_RFTUNE TR(INDENT "Ladění frek", INDENT "Jemné ladění frek. RF") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetrie" #define TR_MULTI_VIDFREQ TR(INDENT "Freq. videa", INDENT "Frekvence videa") #define TR_RF_POWER INDENT "Výkon RF" @@ -827,7 +831,7 @@ #define TR_MENU_GLOBAL_VARS "GLOBÁLNÍ PROMĚNNÉ" #define TR_OWN " \043 " #define TR_DATE "Datum" -#define TR_MONTHS { "Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čec", "Srp", "Zář", "Říj", "Lis", "Pro" } +#define TR_MONTHS { "Led", "Úno", "Bře", "Dub", "Kvě", "Čvn", "Čvc", "Srp", "Zář", "Říj", "Lis", "Pro" } #define TR_ROTARY_ENCODER "R.Enko" #define TR_CHANNELS_MONITOR "MONITOR KANÁLU" #define TR_MIXERS_MONITOR "MONITOR MIXU" @@ -836,8 +840,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloaderu" #define TR_FLASH_EXTERNAL_DEVICE TR("Flash S.Portem", "Flash S.Portem") #define TR_FLASH_RECEIVER_OTA "Flash příjímače OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash modulu BT", "Flash modulu Bluetooth") #define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Flash řízení spotř.", "Flash jednotky řízení spotřeby") #define TR_CURRENT_VERSION TR("Současná ver. ", "Současná verze: ") @@ -945,6 +951,11 @@ #define TR_UNIT "Jednotky" #define TR_TELEMETRY_NEWSENSOR INDENT "Přidat senzor ručně" #define TR_CHANNELRANGE TR(INDENT "Kanály", INDENT "Rozsah kanálů") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", TR("Power src.", "Power source")) #define TR_ANTENNACONFIRM1 "Opravdu přepnout?" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1182,6 +1193,9 @@ #define TR_ADD_MAIN_VIEW "Přidat hlavní panel" #define TR_BACKGROUND_COLOR "Barva pozadí" #define TR_MAIN_COLOR "Hlavní barva" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Prohlížeč textu" #define TR_MENU_INPUTS "\314Vstupy" @@ -1349,3 +1363,13 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index ce4dfc4df..8dea671d9 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -266,7 +266,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\012") #define TR_VUNITSSYSTEM TR("Metrik""Imper.", "Metrisch\0 ""Imperial\0 ") #define LEN_VTELEMUNIT "\003" - #define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" + #define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -439,6 +439,7 @@ #define TR_DISPLAY_TRIMS TR("Trimanzeige", "Trimwerte anzeigen") #define TR_TTRACE TR("Gasquelle", INDENT "Gas-Timerquelle") #define TR_TTRIM TR("Gastrim", INDENT "Gas-Leerlauftrim") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("MittePieps", "Mittelstell. -Pieps") #define TR_USE_GLOBAL_FUNCS TR("Glob. Funkt.", "Globale Funkt verw.") #if defined(PCBSKY9X) && defined(REVX) @@ -448,6 +449,7 @@ #define TR_PPMFRAME INDENT "PPM-Frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH TR("Schalt.", "Schalter") @@ -536,6 +538,7 @@ #define TR_BACKLIGHT_LABEL "LCD-Beleuchtung" #define TR_BLONBRIGHTNESS "An-Helligkeit" #define TR_BLOFFBRIGHTNESS "Aus-Helligkeit" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Farbe" #define TR_SPLASHSCREEN TR("Startbild Ein", "Startbild Anzeigedauer") #define TR_PWR_ON_DELAY "Pwr On delay" @@ -643,6 +646,7 @@ #define TR_RECEIVER_NUM TR("Empf Nr.", "Empfänger Nummer") #define TR_RECEIVER "Empfänger" #define TR_MULTI_RFTUNE TR(INDENT "RF Freq.", INDENT "RF Freq. Feintuning") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR(INDENT "Vid. Freq.", INDENT "Video Frequenz") #define TR_RF_POWER INDENT "RF Power" @@ -843,8 +847,10 @@ #define TR_FLASH_BOOTLOADER TR("Flash bootloader","Flash bootloader") // #define TR_FLASH_EXTERNAL_DEVICE TR("Flash ext. Gerät","Flash externes Gerät") #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetoothmodul") #define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Flash pwr mngt unit", "Flash power management unit") #define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") @@ -958,6 +964,11 @@ #define TR_UNIT "Einheit" #define TR_TELEMETRY_NEWSENSOR INDENT "Sensor hinzufügen ..." #define TR_CHANNELRANGE TR(INDENT "Kanäle", INDENT "Ausgangs Kanäle") //wg 9XR-Pro +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_ANTENNACONFIRM1 "Ant. umschalten" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1062,7 +1073,7 @@ #define TR_LSW_HEADERS_V1 "V1" #define TR_LSW_HEADERS_V2 "V2" #define TR_LSW_HEADERS_ANDSW "UND Schalter" -#define TR_LSW_HEADERS_DURATION "Min Dauer" +#define TR_LSW_HEADERS_DURATION "Dauer" #define TR_LSW_HEADERS_DELAY "Verzögerung" #define TR_GVAR_HEADERS_NAME "Name" @@ -1195,6 +1206,9 @@ #define TR_ADD_MAIN_VIEW "Ansicht hinzufügen" #define TR_BACKGROUND_COLOR "Hintergrundfarbe" #define TR_MAIN_COLOR "Hauptfarbe" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" // ----------------------------- Symbole für Auswahlliste---------- #define TR_MENU_INPUTS "\314Inputs" @@ -1363,3 +1377,13 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 0767a59b0..b612ac429 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -236,8 +236,8 @@ #define TR_SF_SAFETY "---\0 " #endif -#define TR_SF_SCREENSHOT "Screenshot" -#define TR_SF_RESERVE "[reserve]\0" +#define TR_SF_SCREENSHOT "Screenshot" +#define TR_SF_RESERVE "[reserve]\0" #define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_TEST @@ -266,7 +266,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -436,7 +436,8 @@ #define TR_TRIMINC "Trim Step" #define TR_DISPLAY_TRIMS TR("Show Trims", "Display trims") #define TR_TTRACE TR("T-Source", INDENT "Source") -#define TR_TTRIM TR("T-Trim", INDENT "Trim idle only") +#define TR_TTRIM TR("T-Trim-Idle", INDENT "Trim idle only") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Ctr Beep", "Center Beep") #define TR_USE_GLOBAL_FUNCS TR("Glob.Funcs", "Use global funcs") #if defined(PCBSKY9X) && defined(REVX) @@ -446,6 +447,7 @@ #define TR_PPMFRAME INDENT "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH "Switch" @@ -533,6 +535,7 @@ #define TR_BACKLIGHT_LABEL "Backlight" #define TR_BLONBRIGHTNESS "ON brightness" #define TR_BLOFFBRIGHTNESS "OFF brightness" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Color" #define TR_SPLASHSCREEN "Splash screen" #define TR_PWR_ON_DELAY "Pwr On delay" @@ -612,7 +615,7 @@ #define TR_CHANNELS2FAILSAFE "Channels=>Failsafe" #define TR_CHANNEL2FAILSAFE "Channel=>Failsafe" #define TR_MENUMODELSEL TR("MODELSEL", "MODEL SELECTION") -#define TR_MENU_MODEL_SETUP TR("SETUP", "MODEL SETUP") +#define TR_MENU_MODEL_SETUP TR("SETUP", "MODEL SETUP") #define TR_MENUFLIGHTMODES "FLIGHT MODES" #define TR_MENUFLIGHTMODE "FLIGHT MODE" #define TR_MENUHELISETUP "HELI SETUP" @@ -639,6 +642,7 @@ #define TR_RECEIVER_NUM TR("RxNum", "Receiver No.") #define TR_RECEIVER "Receiver" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -673,6 +677,11 @@ #define TR_MULTI_SERVOFREQ TR("Servo rate", "Servo update rate") #define TR_MULTI_MAX_THROW TR("Max. Throw", "Enable max. throw") #define TR_MULTI_RFCHAN TR("RF Channel", "Select RF channel") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_SYNCMENU "[Sync]" #define TR_LIMIT INDENT "Limit" #define TR_MINRSSI "Min Rssi" @@ -685,7 +694,7 @@ #define TR_PITCH_AT_MAX "Pitch max" #define TR_REPEAT_AT_ZERO "Repeat zero" #define TR_SHUTDOWN "SHUTTING DOWN" -#define TR_SAVE_MODEL "Saving model settings" +#define TR_SAVE_MODEL "Saving model settings" #define TR_BATT_CALIB TR("Batt. calib", "Battery calibration") #define TR_CURRENT_CALIB "Current calib" #define TR_VOLTAGE TR(INDENT "Voltage", INDENT "Voltage source") @@ -752,8 +761,8 @@ #define TR_ALARMSWARN "ALARMS" #define TR_SWITCHWARN TR("SWITCH", "CONTROL") #define TR_FAILSAFEWARN "FAILSAFE" -#define TR_TEST_WARNING TR("TESTING", "TEST BUILD") -#define TR_TEST_NOTSAFE "Use for tests only" +#define TR_TEST_WARNING TR("TESTING", "TEST BUILD") +#define TR_TEST_NOTSAFE "Use for tests only" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ", "Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" #define TR_WARN_MULTI_LOWPOWER "Low power mode" @@ -840,8 +849,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE TR("Flash S.Port", "Flash S.Port device") #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Curr Vers: ", "Current version: ") @@ -932,11 +943,10 @@ #define TR_DEL_BUTTON BUTTON(TR("Del", "Delete")) #define TR_RESET_BTN BUTTON("Reset") #define TR_DEBUG "Debug" -#define TR_KEYS_BTN BUTTON(TR("Keys", "Switches")) +#define TR_KEYS_BTN BUTTON("Keys") #define TR_ANALOGS_BTN BUTTON(TR("Anas", "Analogs")) #define TR_TOUCH_NOTFOUND "Touch hardware not found" #define TR_TOUCH_EXIT "Touch screen to exit" -#define TR_CALIBRATION "Calibration" #define TR_SET BUTTON("Set") #define TR_TRAINER "Trainer" #define TR_CHANS "Chans" @@ -960,11 +970,11 @@ #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) -#define LEN_ANTENNA_MODES "\023" -#define TR_ANTENNA_MODES "Internal\0 ""Ask\0 ""Per model\0 ""Internal + External" +#define LEN_ANTENNA_MODES "\023" +#define TR_ANTENNA_MODES "Internal\0 ""Ask\0 ""Per model\0 ""Internal + External" #else -#define LEN_ANTENNA_MODES "\011" -#define TR_ANTENNA_MODES "Internal\0""Ask\0 ""Per model""External" +#define LEN_ANTENNA_MODES "\011" +#define TR_ANTENNA_MODES "Internal\0""Ask\0 ""Per model""External" #endif #define TR_USE_INTERNAL_ANTENNA TR("Use int. antenna", "Use internal antenna") #define TR_USE_EXTERNAL_ANTENNA TR("Use ext. antenna", "Use external antenna") @@ -1012,7 +1022,7 @@ #define STR_EEBACKUP "EEPROM backup" #define STR_FACTORYRESET "Factory reset" #define TR_CONFIRMRESET TR("Erase ALL", "Erase ALL models and settings?") -#define TR_TOO_MANY_LUA_SCRIPTS "Too many Lua scripts!" +#define TR_TOO_MANY_LUA_SCRIPTS "Too many Lua scripts!" #define TR_SPORT_UPDATE_POWER_MODE "SP Power" #define LEN_SPORT_UPDATE_POWER_MODES "\004" #define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 " @@ -1044,7 +1054,7 @@ #define TR_LSW_HEADERS_V1 "V1" #define TR_LSW_HEADERS_V2 "V2" #define TR_LSW_HEADERS_ANDSW "AND Switch" -#define TR_LSW_HEADERS_DURATION "Min Duration" +#define TR_LSW_HEADERS_DURATION "Duration" #define TR_LSW_HEADERS_DELAY "Delay" #define TR_GVAR_HEADERS_NAME "Name" @@ -1194,6 +1204,9 @@ #define TR_ADD_MAIN_VIEW "Add main view" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" #define TR_MENU_INPUTS "\214Inputs" #define TR_MENU_LUA "\222Lua scripts" @@ -1360,3 +1373,13 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 2847c3bf6..a29acd962 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -263,7 +263,7 @@ #define LEN_VUNITSSYSTEM "\010" #define TR_VUNITSSYSTEM "Métrico\0""Imperial" #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -437,6 +437,7 @@ #define TR_DISPLAY_TRIMS "Ver trims" #define TR_TTRACE TR("Fuente-A", INDENT "Fuente acelerador") #define TR_TTRIM TR("Trim-A", INDENT "Trim acelerador") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Beep ctr", "Beep centro") #define TR_USE_GLOBAL_FUNCS TR("Funcs. glob.", "Usar func. globales") #if defined(PCBSKY9X) && defined(REVX) @@ -446,6 +447,7 @@ #define TR_PPMFRAME "Trama PPM" #define TR_REFRESHRATE TR(INDENT "Refresco", INDENT "Velocidad refresco") #define STR_WARN_BATTVOLTAGE TR(INDENT "Salida es VBAT: ", INDENT "Aviso: señal salida es VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequencia" #define TR_SWITCH TR("Interr.", "Interruptor") @@ -534,6 +536,7 @@ #define TR_BLDELAY INDENT"Duración" #define TR_BLONBRIGHTNESS INDENT"MAS brillo" #define TR_BLOFFBRIGHTNESS INDENT"MENOS brillo" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR INDENT "Color" #define TR_SPLASHSCREEN "Pantalla inicio" #define TR_PWR_ON_DELAY TR("Atraso On", "Atraso encendido") @@ -644,6 +647,7 @@ #define TR_RECEIVER_NUM TR("Num Rx", "Receptor No.") #define TR_RECEIVER "Receptor" #define TR_MULTI_RFTUNE TR("Sint.freq.", "RF Freq. sint.fina") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetría" #define TR_MULTI_VIDFREQ TR("Freq.vídeo", "Frecuencia vídeo") #define TR_RF_POWER "RF Power" @@ -844,8 +848,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Flash disp. externo" #define TR_FLASH_RECEIVER_OTA "Flash RX OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX por ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX por int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX por ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX por int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash módulo BT", "Flash módulo bluetooth") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash unid. pwr mngt" #define TR_CURRENT_VERSION TR("Vers. actual", "Versión actual: ") @@ -957,6 +963,11 @@ #define TR_UNIT "Unidad" #define TR_TELEMETRY_NEWSENSOR INDENT "Añadir sensor..." #define TR_CHANNELRANGE INDENT "Canales" +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") #define TR_ANTENNACONFIRM1 "ANTENA EXT." #if defined(PCBX12S) @@ -1195,6 +1206,9 @@ #define TR_ADD_MAIN_VIEW "Añadir vista pral." #define TR_BACKGROUND_COLOR "Color de fondo" #define TR_MAIN_COLOR "Color principal" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Visor de texto" #define TR_MENU_INPUTS "\314Entradas" @@ -1361,4 +1375,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index de8bedec1..ba4b915fe 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -284,7 +284,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -451,6 +451,7 @@ #define TR_DISPLAY_TRIMS "Display Trims" #define TR_TTRACE TR("T-Source", INDENT "Throttle Source") #define TR_TTRIM TR("T-Trim", INDENT "Throttle Trim") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Ctr Beep", "Center Beep") #define TR_USE_GLOBAL_FUNCS "Use Global Funcs" #if defined(PCBSKY9X) && defined(REVX) @@ -460,6 +461,7 @@ #define TR_PPMFRAME TR("PPM frame", INDENT "PPM frame") #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH "Switch" @@ -547,6 +549,7 @@ #define TR_BACKLIGHT_LABEL "Backlight" #define TR_BLONBRIGHTNESS "ON Brightness" #define TR_BLOFFBRIGHTNESS "OFF Brightness" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Color" #define TR_SPLASHSCREEN "Splash screen" #define TR_PWR_ON_DELAY "Pwr On delay" @@ -659,6 +662,7 @@ #define TR_RECEIVER_NUM TR("RxNum", "Receiver No.") #define TR_RECEIVER "Receiver" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -860,8 +864,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Flash External Device" #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") @@ -973,6 +979,11 @@ #define TR_UNIT "Unit" #define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..." #define TR_CHANNELRANGE INDENT "Channel Range" +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) @@ -1060,7 +1071,7 @@ #define TR_LSW_HEADERS_V1 "V1" #define TR_LSW_HEADERS_V2 "V2" #define TR_LSW_HEADERS_ANDSW "AND Switch" -#define TR_LSW_HEADERS_DURATION "Min Duration" +#define TR_LSW_HEADERS_DURATION "Duration" #define TR_LSW_HEADERS_DELAY "Delay" #define TR_GVAR_HEADERS_NAME "Name" @@ -1204,6 +1215,9 @@ #define TR_SETUP_WIDGETS "Setup widgets" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" #define TR_MENU_INPUTS "\314Inputs" @@ -1369,4 +1383,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 92630d9bd..6d8284aae 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -286,7 +286,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\012") #define TR_VUNITSSYSTEM TR("Métr.\0""Impér.", "Métriques\0""Impériales") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -457,6 +457,7 @@ #define TR_DISPLAY_TRIMS TR("Aff. trims", "Affichage trims") #define TR_TTRACE TR("Source gaz", INDENT "Source") #define TR_TTRIM TR("Trim gaz", INDENT "Trim ralenti uniq.") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Bips centr", "Bips centrage") #define TR_USE_GLOBAL_FUNCS TR("Fonc. glob.", "Fonctions globales") #if defined(PCBSKY9X) && defined(REVX) @@ -466,6 +467,7 @@ #define TR_PPMFRAME INDENT "Trame PPM" #define TR_REFRESHRATE INDENT "Période" #define STR_WARN_BATTVOLTAGE TR(INDENT "Signal est VBAT: ", INDENT "ATTENTION: signal est à VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Fréquence" #define TR_SWITCH TR("Inter", "Interrupteur") @@ -554,6 +556,7 @@ #define TR_BACKLIGHT_LABEL "Rétroéclairage" #define TR_BLONBRIGHTNESS "Luminosité ON" #define TR_BLOFFBRIGHTNESS "Luminosité OFF" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Couleur" #define TR_SPLASHSCREEN "Logo d'accueil" #define TR_PWR_ON_DELAY "Délai btn ON" @@ -663,6 +666,7 @@ #define TR_RECEIVER_NUM TR("NumRx", "No. récepteur") #define TR_RECEIVER "Récept." #define TR_MULTI_RFTUNE TR(INDENT "Ajust.fréq", INDENT "Ajustement fréq.") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Télémétrie" #define TR_MULTI_VIDFREQ TR(INDENT "Fréq. vidéo", INDENT "Fréquence vidéo") #define TR_RF_POWER TR("Puiss. RF", "Puissance RF") @@ -743,7 +747,7 @@ #define TR_16CH_WITHOUT_TELEMETRY TR("16CH sans télém.", "16CH sans télémétrie") #define TR_16CH_WITH_TELEMETRY TR("16CH avec télém.", "16CH avec télémétrie") #define TR_8CH_WITH_TELEMETRY TR("8CH avec télém.", "8CH avec télémétrie") -#define TR_EXT_ANTENNA "Antenne externe" +#define TR_EXT_ANTENNA "Antenne Ext." #define TR_PIN "Pin" #define TR_UPDATE_RX_OPTIONS "Sauver options RX?" #define TR_UPDATE_TX_OPTIONS "Sauver options TX?" @@ -862,8 +866,10 @@ #define TR_FLASH_BOOTLOADER "Flasher BootLoader" #define TR_FLASH_EXTERNAL_DEVICE TR("Flasher S.Port", "Flasher S.Port externe") #define TR_FLASH_RECEIVER_OTA "Flasher RX OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash module BT", "Flash module Bluetooth") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flasher pwr mngt unit" #define TR_CURRENT_VERSION "Version courante :" @@ -975,6 +981,11 @@ #define TR_UNIT "Unité" #define TR_TELEMETRY_NEWSENSOR TR(INDENT"Nouveau capteur...", INDENT "Ajout d'un nouveau capteur...") #define TR_CHANNELRANGE TR(INDENT "Canaux", INDENT "Plage de canaux") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_ANTENNACONFIRM1 "Vraiment changer?" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\021" @@ -1069,7 +1080,7 @@ #define TR_LSW_HEADERS_V1 "V1" #define TR_LSW_HEADERS_V2 "V2" #define TR_LSW_HEADERS_ANDSW "ET suppl." -#define TR_LSW_HEADERS_DURATION "Durée min." +#define TR_LSW_HEADERS_DURATION "Durée" #define TR_LSW_HEADERS_DELAY "Délai" #define TR_GVAR_HEADERS_NAME "Nom" @@ -1219,6 +1230,9 @@ #define TR_ADD_MAIN_VIEW "Ajouter vue principale" #define TR_BACKGROUND_COLOR "Couleur de fond" #define TR_MAIN_COLOR "Couleur principale" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Visualisateur de texte" #define TR_MENU_INPUTS "\314Entrées" @@ -1385,4 +1399,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index e5c843a71..47669b967 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -290,7 +290,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\011") #define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metriche\0""Imperiali") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -462,6 +462,7 @@ #define TR_DISPLAY_TRIMS TR("Mos. Trims", "Mostra Trims") #define TR_TTRACE TR("So. motore", INDENT "Sorgente Motore") #define TR_TTRIM TR("Trim Mot.", INDENT "Trim Motore") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Beep al c.", "Beep al centro") #define TR_USE_GLOBAL_FUNCS "Usa Funz. Globali" #if defined(PCBSKY9X) && defined(REVX) @@ -469,10 +470,11 @@ #endif #define TR_PROTO TR(INDENT "Protoc.", INDENT "Protocollo") #define TR_PPMFRAME INDENT "Frame PPM" -#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") -#define STR_WARN_BATTVOLTAGE TR(INDENT "Uscita VBAT: ", INDENT "Att.: livel. uscita VBAT: ") +#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") +#define STR_WARN_BATTVOLTAGE TR(INDENT "Uscita VBAT: ", INDENT "Att.: livel. uscita VBAT: ") +#define TR_WARN_5VOLTS "Attenzione: il livello d'uscita è 5 Volts" #define TR_MS "ms" -#define TR_FREQUENCY INDENT "Frequenza" +#define TR_FREQUENCY INDENT "Frequenza" #define TR_SWITCH "Inter." #define TR_TRIMS "Trims" #define TR_FADEIN "Diss.In" @@ -558,6 +560,7 @@ #define TR_BACKLIGHT_LABEL TR("Retroillu.", "Retroilluminazione") #define TR_BLONBRIGHTNESS TR("Lumin. ON", "Luminosità ON") #define TR_BLOFFBRIGHTNESS TR("Lumin. OFF", "Luminosità OFF") +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Colore" #define TR_SPLASHSCREEN TR("Sch. avvio", "Schermata d'avvio") #define TR_PWR_ON_DELAY "Rit. accens." @@ -664,6 +667,7 @@ #define TR_RECEIVER_NUM TR("RxNum", "Ricevente N.") #define TR_RECEIVER "Ricevente" #define TR_MULTI_RFTUNE TR("Tune RF", "Tune fine Freq. RF") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetria" #define TR_MULTI_VIDFREQ TR("Freq. video", "Frequenza video") #define TR_RF_POWER "Potenza RF" @@ -856,29 +860,31 @@ #define TR_MENU_GLOBAL_VARS "VARIABILI GLOBALI" #define TR_OWN "Fase" #define TR_DATE "Data" -#define TR_MONTHS { "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Auo", "Set", "Ott", "Nov", "Dic" } +#define TR_MONTHS { "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic" } #define TR_ROTARY_ENCODER "R.E." #define TR_CHANNELS_MONITOR "MONITOR CANALI" #define TR_MIXERS_MONITOR "MONITOR MIXER" #define TR_PATH_TOO_LONG "Path troppo lungo" #define TR_VIEW_TEXT "Vedi testo" -#define TR_FLASH_BOOTLOADER "Prog. bootloader" -#define TR_FLASH_EXTERNAL_DEVICE "Progr. dispositivo Esterno" -#define TR_FLASH_RECEIVER_OTA TR("Prog. RX OTA", INDENT "Prog. ricevente OTA") -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_BOOTLOADER TR("Prog. bootloader", "Programma bootloader") +#define TR_FLASH_EXTERNAL_DEVICE TR("Prog. disp. est.", "Programma dispositivo esterno") +#define TR_FLASH_RECEIVER_OTA TR("Prog. RX OTA", INDENT "Programma RX OTA") +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA TR("Prog. RX da OTA est.", INDENT "Prog. RX da OTA esterno") +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA TR("Prog. RX da OTA int.", INDENT "Prog. RX da OTA interno") +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA TR("Prog. FC da OTA est.", INDENT "Prog. FC da OTA esterno") +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA TR("Prog. FC da OTA int.", INDENT "Prog. FC da OTA interno") #define TR_FLASH_BLUETOOTH_MODULE TR("Prog. mod. BT", INDENT "Prog. modulo Bluetooth") -#define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Prog. PMU", "Program. PMU") +#define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Prog. PMU", "Programma PMU") #define TR_CURRENT_VERSION TR("Vers. currente ", "Versione corrente: ") -#define TR_FLASH_INTERNAL_MODULE "Progr. modulo int." -#define TR_FLASH_EXTERNAL_MODULE "Progr. modulo est." -#define TR_FLASH_INTERNAL_MULTI "Prog. Multi int." -#define TR_FLASH_EXTERNAL_MULTI "Prog. Multi est." +#define TR_FLASH_INTERNAL_MODULE TR("Prog. modulo int.", "Programma modulo interno") +#define TR_FLASH_EXTERNAL_MODULE TR("Prog. modulo est.", "Programma modulo esterno") +#define TR_FLASH_INTERNAL_MULTI TR("Prog. MULTI int.", "Programma MULTI interno") +#define TR_FLASH_EXTERNAL_MULTI TR("Prog. MULTI est.", "Programma MULTI esterno") #define TR_FIRMWARE_UPDATE_ERROR TR(INDENT "Errore agg. FW",INDENT "Errore aggiornamento firmware") #define TR_FIRMWARE_UPDATE_SUCCESS "Aggiornamento" BREAKSPACE "riuscito" #define TR_WRITING "Scrittura..." -#define TR_CONFIRM_FORMAT "Confermi Formattazione?" -#define TR_INTERNALRF "Modulo Interno" +#define TR_CONFIRM_FORMAT "Confermi formattazione?" +#define TR_INTERNALRF "Modulo interno" #define TR_INTERNAL_MODULE TR("Modulo int.", "Modulo interno") #define TR_EXTERNAL_MODULE TR("Modulo est.", "Modulo esterno") #define TR_OPENTX_UPGRADE_REQUIRED "OpenTX richiede aggiornamento" @@ -895,8 +901,8 @@ #define TR_HOLD_UPPERCASE "HOLD" #define TR_NONE "None" #define TR_NONE_UPPERCASE "NONE" -#define TR_MENUSENSOR "SENSOR" -#define TR_POWERMETER_PEAK "Peak" +#define TR_MENUSENSOR "SENSORE" +#define TR_POWERMETER_PEAK "Picco" #define TR_POWERMETER_POWER "Potenza" #define TR_POWERMETER_ATTN "Att." #define TR_POWERMETER_FREQ "Freq." @@ -909,7 +915,7 @@ #define TR_COUNTRY_CODE TR("Cod. Paese", "Codice del Paese") #define TR_USBMODE "Modo USB" #define TR_JACK_MODE "Modo JACK" -#define TR_VOICE_LANGUAGE "Lingua Voce" +#define TR_VOICE_LANGUAGE "Lingua vocale" #define TR_UNITS_SYSTEM "Unità" #define TR_EDIT "Modifica" #define TR_INSERT_BEFORE "Inserisci prima" @@ -957,11 +963,11 @@ #define TR_DEL_BUTTON BUTTON(TR("Canc.", "Cancella")) #define TR_RESET_BTN "[Reset]" #define TR_DEBUG "Debug" -#define TR_KEYS_BTN BUTTON(TR("SW","Interruttori")) -#define TR_ANALOGS_BTN BUTTON(TR("Analogico","Analogici")) -#define TR_TOUCH_NOTFOUND "Schermo touch non trovato" -#define TR_TOUCH_EXIT "Tocca lo schermo per uscire" -#define TR_CALIBRATION TR("Calibraz.", "Calibrazione") +#define TR_KEYS_BTN BUTTON(TR("SW", "Tasti")) +#define TR_ANALOGS_BTN BUTTON("Analogici") +#define TR_TOUCH_NOTFOUND "Schermo touch non trovato" +#define TR_TOUCH_EXIT "Tocca lo schermo per uscire" +#define TR_CALIBRATION TR("Calibraz.", "Calibrazione") #define TR_SET "[Set]" #define TR_TRAINER TR("Trainer", "Maestro/Allievo") #define TR_CHANS "Canali" @@ -979,6 +985,11 @@ #define TR_TELEMETRY_NEWSENSOR INDENT "Aggiungi nuovo sensore" #define TR_CHANNELRANGE INDENT "Numero Canali" #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") +#define TR_AFHDS3_RX_FREQ TR("Freq. RX", "Frequenza RX") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetria") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Pot. att.", "Potenza attuale") +#define TR_AFHDS3_POWER_SOURCE TR("Sorg. al.", "Sorgente alimentazione") #define TR_ANTENNACONFIRM1 "ANTENNA EST." #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1216,6 +1227,9 @@ #define TR_ADD_MAIN_VIEW "Aggiungi vista princ." #define TR_BACKGROUND_COLOR "Colore background" #define TR_MAIN_COLOR "Colore principale" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Visualizzatore testi" #define TR_MENU_INPUTS "\314Ingressi" @@ -1235,12 +1249,12 @@ #define TR_MENU_OTHER "Altro" #define TR_MENU_INVERT "Inverti" #define TR_JITTER_FILTER "Filtro ADC" -#define TR_RTC_CHECK TR("Controllo RTC", "Controllo voltaggio RTC") -#define TR_AUTH_FAILURE "Auth-failure" +#define TR_RTC_CHECK TR("Controllo RTC", "Controllo volt. RTC") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" -#define ZSTR_R9PW "R9PW" +#define ZSTR_R9PW "R9PW" #define ZSTR_RAS "SWR" #define ZSTR_A1 "A1" #define ZSTR_A2 "A2" @@ -1383,3 +1397,13 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 38fc8e581..ca6de810d 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -267,7 +267,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Mtrsch""Engels", "Metrisch\0 ""Engels\0 ") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -438,6 +438,7 @@ #define TR_DISPLAY_TRIMS "Toon Trims" #define TR_TTRACE TR("T-Source", INDENT "Source") #define TR_TTRIM TR("T-Trim", INDENT "Trim Idle Only") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Ctr Beep", "Center Beep") #define TR_USE_GLOBAL_FUNCS TR("Glob.Funcs", "Globale Functies") #if defined(PCBSKY9X) && defined(REVX) @@ -447,6 +448,7 @@ #define TR_PPMFRAME INDENT "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH TR("Schak.", "Schakelaar") @@ -535,6 +537,7 @@ #define TR_BACKLIGHT_LABEL "LCD-Verlichting" #define TR_BLONBRIGHTNESS "Aan-Helderheid" #define TR_BLOFFBRIGHTNESS "Uit-Helderheid" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Kleur" #define TR_SPLASHSCREEN "Startscherm Aan" #define TR_PWR_ON_DELAY "Pwr On delay" @@ -646,6 +649,7 @@ #define TR_RECEIVER_NUM TR("RxNum", "Receiver Nr.") #define TR_RECEIVER "Receiver" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -847,8 +851,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Flash extern Apparaat" #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") @@ -960,6 +966,11 @@ #define TR_UNIT "Eenheid" #define TR_TELEMETRY_NEWSENSOR INDENT "Sensor toevoegen ..." #define TR_CHANNELRANGE TR(INDENT "Kanalen", INDENT "Uitgangs Kanalen") //wg 9XR-Pro +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_ANTENNACONFIRM1 "Antennes wisselen?" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1052,7 +1063,7 @@ #define TR_LSW_HEADERS_V1 "Var1" #define TR_LSW_HEADERS_V2 "Var2" #define TR_LSW_HEADERS_ANDSW "EN-Schakelaar" -#define TR_LSW_HEADERS_DURATION "Min. Duur" +#define TR_LSW_HEADERS_DURATION "Duur" #define TR_LSW_HEADERS_DELAY "Vertraging" #define TR_GVAR_HEADERS_NAME "Name" @@ -1202,6 +1213,9 @@ #define TR_ADD_MAIN_VIEW "Add main view" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" @@ -1369,4 +1383,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 69053d33b..afbd46c7c 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -284,7 +284,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") /*8 decimal*/ #define TR_VUNITSSYSTEM TR("Metr. ""Imper.", "Metryczn""Imperial") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -458,6 +458,7 @@ #define TR_DISPLAY_TRIMS TR("Pok.Trym.","Pokaż Trymery") #define TR_TTRACE TR("Źród gaz", INDENT "Źródło gazu ") #define TR_TTRIM TR("TryGaz", INDENT "TrymWolnObrotó") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("ŚrodBeep", "Pikn.Środka") #define TR_USE_GLOBAL_FUNCS TR("Funk.Glb.","Użyj Funkcji Glb") #if defined(PCBSKY9X) && defined(REVX) @@ -467,6 +468,7 @@ #define TR_PPMFRAME INDENT "Ramka PPM" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH "Przełą" @@ -554,6 +556,7 @@ #define TR_BACKLIGHT_LABEL "Podświetl" #define TR_BLONBRIGHTNESS "Jasnośc wł." #define TR_BLOFFBRIGHTNESS "Jasność wył." +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Color" #define TR_SPLASHSCREEN "Logo ekranu" #define TR_PWR_ON_DELAY "Pwr On delay" @@ -660,6 +663,7 @@ #define TR_RECEIVER_NUM TR("Nr RX", "Nr odbiornika") #define TR_RECEIVER INDENT "Receiver" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -861,8 +865,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Sflashuj Moduł Zewnętrzny" #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") @@ -975,6 +981,11 @@ #define TR_TELEMETRY_NEWSENSOR INDENT "Dodaj nowy czujnik..." #define TR_CHANNELRANGE TR(INDENT "ZakrKn",INDENT "Zakres kanału") #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1212,6 +1223,9 @@ #define TR_ADD_MAIN_VIEW "Add main view" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" #define TR_MENU_INPUTS "\314Wejści" @@ -1378,4 +1392,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 2c5d8a499..c78c5ed17 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -280,7 +280,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial") #define LEN_VTELEMUNIT "\003" - #define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" + #define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -444,6 +444,7 @@ #define TR_DISPLAY_TRIMS "Display Trims" #define TR_TTRACE TR("T-Trace", INDENT "T-Trace") #define TR_TTRIM TR("T-Trim", INDENT "T-Trim") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR "Ctr Beep" #define TR_USE_GLOBAL_FUNCS "Use Global Funcs" #if defined(PCBSKY9X) && defined(REVX) @@ -453,6 +454,7 @@ #define TR_PPMFRAME "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH "Chave" @@ -540,6 +542,7 @@ #define TR_BACKLIGHT_LABEL "Backlight" #define TR_BLONBRIGHTNESS "ON Brightness" #define TR_BLOFFBRIGHTNESS "OFF Brightness" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_BLCOLOR "Color" #define TR_SPLASHSCREEN "Splash screen" #define TR_PWR_ON_DELAY "Pwr On delay" @@ -651,6 +654,7 @@ #define TR_RECEIVER "Receiver" #define TR_SYNCMENU "Sync [MENU]" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -851,8 +855,10 @@ #define TR_FLASH_BOOTLOADER "Flash bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Flash External Device" #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") @@ -965,6 +971,11 @@ #define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..." #define TR_CHANNELRANGE INDENT "Channel Range" #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1051,7 +1062,7 @@ #define TR_LSW_HEADERS_V1 "V1" #define TR_LSW_HEADERS_V2 "V2" #define TR_LSW_HEADERS_ANDSW "AND Switch" -#define TR_LSW_HEADERS_DURATION "Min Duration" +#define TR_LSW_HEADERS_DURATION "Duration" #define TR_LSW_HEADERS_DELAY "Delay" #define TR_GVAR_HEADERS_NAME "Name" @@ -1201,6 +1212,9 @@ #define TR_ADD_MAIN_VIEW "Add main view" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" #define TR_MENU_INPUTS "\314Inputs" @@ -1367,4 +1381,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 6210631e5..28033ac63 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -284,7 +284,7 @@ #define LEN_VUNITSSYSTEM TR("\006", "\010") #define TR_VUNITSSYSTEM TR("Metri.""Imper.", "Metriska""Imperial") #define LEN_VTELEMUNIT "\003" -#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz" +#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0" #define STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -460,6 +460,7 @@ #define TR_DISPLAY_TRIMS "Display Trims" #define TR_TTRACE TR("Följ Gas", INDENT "Följ Gas") #define TR_TTRIM TR("Gastrim", INDENT "Gastrim") +#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch") #define TR_BEEPCTR TR("Cent.pip", "Centerpip") #define TR_USE_GLOBAL_FUNCS TR("Glob.Funkt", "Använd Global Funk.") #if defined(PCBSKY9X) && defined(REVX) @@ -469,6 +470,7 @@ #define TR_PPMFRAME INDENT "PPM-paket" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_WARN_5VOLTS "Warning: output level is 5 volts" #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequency" #define TR_SWITCH "Brytare" @@ -556,6 +558,7 @@ #define TR_BACKLIGHT_LABEL "Belysning" #define TR_BLONBRIGHTNESS "På Ljusstyrka" #define TR_BLOFFBRIGHTNESS "Av Ljusstyrka" +#define TR_KEYS_BACKLIGHT "Keys backlight" #define TR_SPLASHSCREEN "Startbild" #define TR_PWR_ON_DELAY "Pwr On delay" #define TR_PWR_OFF_DELAY "Pwr Off delay" @@ -663,6 +666,7 @@ #define TR_RECEIVER "Receiver" #define TR_SYNCMENU "Synk [MENU]" #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") +#define TR_MULTI_RFPOWER "RF power" #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") #define TR_RF_POWER "RF Power" @@ -864,8 +868,10 @@ #define TR_FLASH_BOOTLOADER "Skriv BootLoader" #define TR_FLASH_EXTERNAL_DEVICE "Flash External Device" #define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA" -#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA" +#define TR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA "Flash RX by ext. OTA" +#define TR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA "Flash RX by int. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA "Flash FC by ext. OTA" +#define TR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA "Flash FC by int. OTA" #define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" #define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") @@ -978,6 +984,11 @@ #define TR_TELEMETRY_NEWSENSOR INDENT "Lägg till sensor..." #define TR_CHANNELRANGE INDENT "Kanalområde" #define TR_RXFREQUENCY TR("Rx Freqency", "Rx Servo Frequency") +#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency") +#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry") +#define TR_AFHDS3_ONE_TO_MANY "Multicast" +#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power") +#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source") #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" @@ -1215,6 +1226,9 @@ #define TR_ADD_MAIN_VIEW "Add main view" #define TR_BACKGROUND_COLOR "Background color" #define TR_MAIN_COLOR "Main color" +#define TR_BAR2_COLOR "Secondary bar color" +#define TR_BAR1_COLOR "Main bar color" +#define TR_TEXT_COLOR "Text color" #define TR_TEXT_VIEWER "Text Viewer" #define TR_MENU_INPUTS "\314Inputs" @@ -1381,4 +1395,14 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" +#define ZSTR_SERVO_CURRENT "SrvA" +#define ZSTR_SERVO_VOLTAGE "SrvV" +#define ZSTR_SERVO_TEMPERATURE "SrvT" +#define ZSTR_SERVO_STATUS "SrvS" diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index dfe97c014..c026e6a8d 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -95,10 +95,10 @@ #endif #define LEN_EXTERNAL_MODULE_PROTOCOLS "\014" -#define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""R9MLP\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite\0 ""FLYSKY " +#define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""GHST\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite\0 ""AFHDS3\0 " #define LEN_FLYSKY_PROTOCOLS "\006" -#define TR_FLYSKY_PROTOCOLS " PWM+i"" PWM+s"" PPM+i"" PPM+s" +#define TR_FLYSKY_PROTOCOLS #define LEN_INTERNAL_MODULE_PROTOCOLS LEN_EXTERNAL_MODULE_PROTOCOLS #define TR_INTERNAL_MODULE_PROTOCOLS TR_EXTERNAL_MODULE_PROTOCOLS @@ -136,7 +136,16 @@ #define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX" #define LEN_MULTI_PROTOCOLS "\007" -#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""FlyZone""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 " +#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""FlyZone""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyarte""ESky-v2""DSM RX\0""JJRC345""Q90C\0 " + +#define LEN_MULTI_POWER "\005" +#define TR_MULTI_POWER "10mW\0""25mW\0""50mW\0""100mW""200mW""300mW""500mW""1W\0 ""2W\0 " + +#define LEN_AFHDS3_PROTOCOLS "\x008" +#define TR_AFHDS3_PROTOCOLS "PWM/IBUS""PWM/SBUS""PPM/IBUS""PPM/SBUS" + +#define LEN_AFHDS3_POWERS "\006" +#define TR_AFHDS3_POWERS "25 mW\0""100 mW""500 mW""1 W\0 ""2 W\0 " #define LEN_PPM_POL "\001" #define TR_PPM_POL "+""-" diff --git a/radio/util/build-firmware.py b/radio/util/build-firmware.py index 76bade5b6..c27e6b58a 100755 --- a/radio/util/build-firmware.py +++ b/radio/util/build-firmware.py @@ -93,12 +93,14 @@ def main(): maxsize = 65536 * 8 elif options[optcount] == "x7": cmake_options["PCB"] = "X7" - firmware_options = options_taranis_x9dp + cmake_options["AFHDS3"] = "YES" + firmware_options = options_taranis_x7 maxsize = 65536 * 8 elif options[optcount] == "x7access": cmake_options["PCB"] = "X7" cmake_options["PCBREV"] = "ACCESS" - firmware_options = options_taranis_x9dp + cmake_options["AFHDS3"] = "YES" + firmware_options = options_taranis_x7 maxsize = 65536 * 8 elif board_name == "xlite": cmake_options["PCB"] = "XLITE" @@ -119,6 +121,7 @@ def main(): elif board_name == "x9d+2019": cmake_options["PCB"] = "X9D+" cmake_options["PCBREV"] = "2019" + cmake_options["AFHDS3"] = "YES" firmware_options = options_taranis_x9dp maxsize = 65536 * 8 elif board_name == "x9e": @@ -148,6 +151,11 @@ def main(): cmake_options["PCBREV"] = "T16" firmware_options = options_jumper_t16 maxsize = 2 * 1024 * 1024 + elif board_name == "t18": + cmake_options["PCB"] = "X10" + cmake_options["PCBREV"] = "T18" + firmware_options = options_jumper_t18 + maxsize = 2 * 1024 * 1024 elif board_name == "tx16s": cmake_options["PCB"] = "X10" cmake_options["PCBREV"] = "TX16S" diff --git a/radio/util/fwoptions.py b/radio/util/fwoptions.py index 8ee448f11..140cf4b47 100755 --- a/radio/util/fwoptions.py +++ b/radio/util/fwoptions.py @@ -71,13 +71,13 @@ options_taranis_x9d = { "haptic": ("HAPTIC", "YES", "NO"), "nogvars": ("GVARS", "NO", "YES"), "sqt5font": ("FONT", "SQT5", None), + "noras": ("RAS", "NO", "YES"), "faimode": ("FAI", "YES", None), "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), - "internalppm": ("INTERNAL_MODULE_PPM", "YES", "NO"), - "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "afhds3": ("AFHDS3", "YES", "NO") } options_taranis_x9dp = { @@ -90,10 +90,21 @@ options_taranis_x9dp = { "faimode": ("FAI", "YES", None), "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), - "internalppm": ("INTERNAL_MODULE_PPM", "YES", "NO"), - "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "afhds3": ("AFHDS3", "YES", "NO") +} +options_taranis_x7 = { + "noheli": ("HELI", "NO", "YES"), + "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), + "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"), + "nogvars": ("GVARS", "NO", "YES"), + "sqt5font": ("FONT", "SQT5", None), + "faimode": ("FAI", "YES", None), + "faichoice": ("FAI", "CHOICE", None), + "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), + "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), } options_taranis_x9lite = { @@ -101,16 +112,13 @@ options_taranis_x9lite = { "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"), "nogvars": ("GVARS", "NO", "YES"), - "autoupdate": ("AUTOUPDATE", "YES", None), "sqt5font": ("FONT", "SQT5", None), - "noras": ("RAS", "NO", "YES"), "faimode": ("FAI", "YES", None), "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), - "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), - "internalpxx1": ("INTERNAL_MODULE_PXX1", "YES", "NO"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "afhds3": ("AFHDS3", "YES", "NO") } options_taranis_xlite = { @@ -122,9 +130,9 @@ options_taranis_xlite = { "faimode": ("FAI", "YES", None), "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), - "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "afhds3": ("AFHDS3", "YES", "NO") } options_taranis_xlites = { @@ -132,15 +140,13 @@ options_taranis_xlites = { "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"), "nogvars": ("GVARS", "NO", "YES"), - "autoupdate": ("AUTOUPDATE", "YES", None), "sqt5font": ("FONT", "SQT5", None), "faimode": ("FAI", "YES", None), "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), - "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), - "internalpxx1": ("INTERNAL_MODULE_PXX1", "YES", "NO"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "afhds3": ("AFHDS3", "YES", "NO") } options_taranis_x9e = { @@ -152,11 +158,11 @@ options_taranis_x9e = { "faimode": ("FAI", "YES", None), "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), - "internalppm": ("INTERNAL_MODULE_PPM", "YES", "NO"), "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), "horussticks": ("STICKS", "HORUS", "STANDARD"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "afhds3": ("AFHDS3", "YES", "NO") } options_horus_x12s = { @@ -170,7 +176,7 @@ options_horus_x12s = { "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), "pcbdev": ("PCBREV", "10", None), "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), - "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)] + "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)], } options_horus_x10 = { @@ -183,7 +189,7 @@ options_horus_x10 = { "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), - "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)] + "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)], } options_horus_x10express = { @@ -196,7 +202,7 @@ options_horus_x10express = { "faichoice": ("FAI", "CHOICE", None), "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), - "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None) + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), } options_jumper_t12 = { @@ -209,6 +215,7 @@ options_jumper_t12 = { "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), "internalmulti": ("INTERNAL_MODULE_MULTI", "YES", "NO"), + "afhds3": ("AFHDS3", "YES", "NO") } options_jumper_t16 = { @@ -224,6 +231,18 @@ options_jumper_t16 = { "bluetooth": ("BLUETOOTH", "YES", "NO"), } +options_jumper_t18 = { + "noheli": ("HELI", "NO", "YES"), + "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), + "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"), + "nogvars": ("GVARS", "NO", "YES"), + "faimode": ("FAI", "YES", None), + "faichoice": ("FAI", "CHOICE", None), + "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), + "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), + "bluetooth": ("BLUETOOTH", "YES", "NO"), +} + options_radiomaster_tx16s = { "noheli": ("HELI", "NO", "YES"), "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), diff --git a/radio/util/tts_de.py b/radio/util/tts_de.py index 793d3fb85..f4f292d61 100755 --- a/radio/util/tts_de.py +++ b/radio/util/tts_de.py @@ -29,7 +29,7 @@ for i, (s, f) in enumerate([("Wolt", "volt0"), ("Grad Celsius", "celsius0"), ("Grad Fahrenheit", "fahr0"), ("Prozent", "percent0"), - ("Milliampär pro stunde", "mamph0"), + ("Milliampär stunde", "mamph0"), ("Watt", "watt0"), ("Milli Watt", "mwatt0"), ("D B", "db0"), @@ -82,7 +82,7 @@ for s, f in [("Inaktivitätsalarm", "inactiv"), ("timer zwei abgelaufen", "timovr2"), ("timer drei abgelaufen", "timovr3"), ("Sensor verloren", "sensorko"), - ("Willkommen bei open te ix", "hello"), + ("Willkommen bei open t x", "hello"), ]: systemSounds.append((s, filename(f))) for i, s in enumerate(["Uhr", "Uhr", "Sender", "Empfang", "A1", "A2", "Hoehe", "Motor", diff --git a/radio/util/tts_en.py b/radio/util/tts_en.py index dff2e29dd..616abe516 100755 --- a/radio/util/tts_en.py +++ b/radio/util/tts_en.py @@ -38,6 +38,9 @@ for i, (s, f) in enumerate([("volt", "volt0"), ("volts", "volt1"), ("milliliter", "ml0"), ("milliliters", "ml1"), ("fluid ounce", "founce0"), ("fluid ounces", "founce1"), ("milliliter per minute", "mlpm0"), ("milliliters per minute", "mlpm1"), + ("hertz", "hertz0"), ("hertz", "hertz1"), + ("milisecond", "ms0"), ("miliseconds", "ms1"), + ("microsecond", "us0"), ("microseconds", "us1"), ("hour", "hour0"), ("hours", "hour1"), ("minute", "minute0"), ("minutes", "minute1"), ("second", "second0"), ("seconds", "second1"), @@ -74,6 +77,8 @@ for s, f in [("trim center", "midtrim"), systemSounds.append((s, filename(f))) for i, (s, f) in enumerate([("armed", "armed"), ("disarmed", "disarm"), + ("throttle cut", "thrcut"), + ("throttle active", "thract"), ("gear!, up!", "gearup"), ("gear!, down!", "geardn"), ("flaps!, up!", "flapup"), @@ -90,6 +95,8 @@ for i, (s, f) in enumerate([("armed", "armed"), ("crow!, off!", "crowof"), ("rf. signal!, low!", "siglow"), ("rf. signal!, critical!", "sigcrt"), + ("LQ", "lq"), + ("RF mode", "rfmode"), ("high. speed. mode!, active", "spdmod"), ("thermal. mode!, on", "thmmod"), ("normal. mode!, on", "nrmmod"), @@ -119,5 +126,13 @@ for i, (s, f) in enumerate([("armed", "armed"), ("flight mode thermal", "fm-thm"), ("flight mode thermal left", "fm-thl"), ("flight mode thermal right", "fm-thr"), + ("flight mode stabilize", "fm-stb"), + ("flight mode horizon", "fm-hor"), + ("flight mode angle", "fm-ang"), + ("flight mode idle up 1", "fm-id1"), + ("flight mode idle up 2", "fm-id2"), + ("low rate", "ratlow"), + ("medium rate", "ratmed"), + ("high rate", "rathi"), ]): sounds.append((s, filename(f))) diff --git a/radio/util/tts_es.py b/radio/util/tts_es.py index 01d28d3dd..897b6b9e4 100755 --- a/radio/util/tts_es.py +++ b/radio/util/tts_es.py @@ -61,24 +61,27 @@ for s, f in [("me tienes abandonada", "inactiv"), ("trim centrado", "midtrim"), ("potenciómetro centrado", "midpot"), ("trim al máximo", "maxtrim"), - ("trim al mínima", "mintrim"), + ("trim al mínimo", "mintrim"), ("20 segundos", "timer20"), ("30 segundos", "timer30"), - ("assorbimiento elevado", "highmah"), - ("temperatura elevada", "hightemp"), + ("consumo alto", "highmah"), + ("temperatura alta", "hightemp"), ("Alarma A1", "a1_org"), ("A1 crítica", "a1_red"), ("Alarma A2", "a2_org"), ("A2 crítica", "a2_red"), ("Bienvenido a open t equis", "hello"), - ("recepcion de señal baja", "rssi_org"), - ("recepción de señal crítica", "rssi_red"), + ("señal baja", "rssi_org"), + ("señal crítica", "rssi_red"), ("Problemas con la antena del transmisor", "swr_red"), ("Sin telemetría", "telemko"), ("Telemetría disponible", "telemok"), - ("servo overload", "servoko"), - ("power overload", "rxko"), - ("El receptor esta conectado", "modelpwr"), + ("sobrecarga de servo", "servoko"), + ("sobrecarga de potencia", "rxko"), + ("El receptor aún está encendido", "modelpwr"), + ("cronómetro uno terminado", "timovr1"), + ("cronómetro dos terminado", "timovr2"), + ("cronómetro tres terminado", "timovr3"), ]: systemSounds.append((s, filename(f))) for i, s in enumerate(["cronómetro", "cronómetro", "transmisión", "recepción", "A1", "A2", "altitud", "motor", @@ -102,14 +105,14 @@ for i, (s, f) in enumerate([("tren arriba.", "gearup"), ("modo de velocidad", "spdmod"), ("modo de térmica", "thmmod"), ("modo de vuelo normal", "nrmmod"), - ("fase de vuelo 1", "fltmd1"), - ("fase de vuelo 2", "fltmd2"), - ("fase de vuelo 3", "fltmd3"), - ("fase de vuelo 4", "fltmd4"), - ("fase de vuelo 5", "fltmd5"), - ("fase de vuelo 6", "fltmd6"), - ("fase de vuelo 7", "fltmd7"), - ("fase de vuelo 8", "fltmd8"), - ("fase de vuelo 9", "fltmd9"), + ("modo de vuelo 1", "fltmd1"), + ("modo de vuelo 2", "fltmd2"), + ("modo de vuelo 3", "fltmd3"), + ("modo de vuelo 4", "fltmd4"), + ("modo de vuelo 5", "fltmd5"), + ("modo de vuelo 6", "fltmd6"), + ("modo de vuelo 7", "fltmd7"), + ("modo de vuelo 8", "fltmd8"), + ("modo de vuelo 9", "fltmd9"), ]): sounds.append((s, filename(f))) diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index 98d6653e6..fbf8f7166 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -106,6 +106,10 @@ cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=TX16S ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt +cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T18 ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=EXPRESS ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt diff --git a/tools/build-companion-release.sh b/tools/build-companion-release.sh index 34757a3e8..b73ce8ed2 100755 --- a/tools/build-companion-release.sh +++ b/tools/build-companion-release.sh @@ -62,6 +62,10 @@ cmake ${COMMON_OPTIONS} -DPCB=X7 ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt +cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=ACCESS ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T12 ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt @@ -102,6 +106,10 @@ cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=TX16S ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt +cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T18 ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=EXPRESS ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt diff --git a/tools/build-frsky.py b/tools/build-frsky.py index 5a5cb26ac..fc33d2b80 100755 --- a/tools/build-frsky.py +++ b/tools/build-frsky.py @@ -11,141 +11,93 @@ import tempfile boards = { "XLITE_FCC": { "PCB": "XLITE", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", "MODULE_SIZE_STD": "NO", "PPM": "NO", "DSM2": "NO", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "SBUS": "NO", }, "XLITE_LBT": { "PCB": "XLITE", "MODULE_PROTOCOL_D8": "NO", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", "MODULE_SIZE_STD": "NO", "PPM": "NO", "DSM2": "NO", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "SBUS": "NO", }, "XLITES": { "PCB": "XLITES", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", "AUTOUPDATE": "YES", "PXX1": "YES", "XJT": "NO", "MODULE_SIZE_STD": "NO", "PPM": "NO", "DSM2": "NO", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "SBUS": "NO", }, "X9LITE": { "PCB": "X9LITE", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", "AUTOUPDATE": "YES", "PXX1": "YES", "XJT": "NO", "MODULE_SIZE_STD": "NO", "PPM": "NO", "DSM2": "NO", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "SBUS": "NO", "DEFAULT_MODE": "2", }, "X9LITES": { "PCB": "X9LITES", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", "AUTOUPDATE": "YES", "PXX1": "YES", "XJT": "NO", "MODULE_SIZE_STD": "NO", "PPM": "NO", "DSM2": "NO", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "SBUS": "NO", "DEFAULT_MODE": "2", }, + "X9D+2019": { + "PCB": "X9D+", + "PCBREV": "2019", + "AUTOUPDATE": "YES", + "PXX1": "YES", + "DEFAULT_MODE": "2", + }, "X9D+": { "PCB": "X9D+", - "PCBREV": "2019", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "AUTOUPDATE": "YES", - "PXX1": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X9E": { "PCB": "X9E", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X7_FCC": { "PCB": "X7", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X7_LBT": { "PCB": "X7", "MODULE_PROTOCOL_D8": "NO", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X7ACCESS": { "PCB": "X7", "PCBREV": "ACCESS", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", "AUTOUPDATE": "YES", "PXX1": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X10S": { "PCB": "X10", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X10SExpress": { "PCB": "X10", "PCBREV": "EXPRESS", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, "X12S": { "PCB": "X12S", - "LUA": "NO_MODEL_SCRIPTS", - "GVARS": "YES", - "MULTIMODULE": "NO", - "CROSSFIRE": "NO", "DEFAULT_MODE": "2", }, } @@ -155,13 +107,21 @@ translations = [ "CZ" ] +common_options = { + "MULTIMODULE": "NO", + "CROSSFIRE": "NO", + "AFHDS3": "NO", + "GVARS": "YES", + "LUA": "NO_MODEL_SCRIPTS", +} + def timestamp(): return datetime.datetime.now().strftime("%y%m%d") def build(board, translation, srcdir): - cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in boards[board].items()]) + cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in list(boards[board].items()) + list(common_options.items())]) cwd = os.getcwd() if not os.path.exists("output"): os.mkdir("output") diff --git a/tools/build-jumper.py b/tools/build-jumper.py index ab3fb9e45..6e7f3d733 100755 --- a/tools/build-jumper.py +++ b/tools/build-jumper.py @@ -25,6 +25,12 @@ boards = { "PCBREV": "T16", "INTERNAL_MODULE_MULTI": "YES", "DEFAULT_MODE": "2", + }, + "T18": { + "PCB": "X10", + "PCBREV": "T18", + "INTERNAL_MODULE_MULTI": "YES", + "DEFAULT_MODE": "2", } } diff --git a/tools/clang-format.sh b/tools/clang-format.sh new file mode 100755 index 000000000..9a6111beb --- /dev/null +++ b/tools/clang-format.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Automatic indentation of all .c, .cpp and .h-files using clang-format +# based on https://github.com/opentx/opentx/wiki/OpenTX-Code-Style-Guide + +# clang-format version 10.0.0 + +for i in $(find ./ -name "*.c" -or -name "*.cpp" -or -name "*.h") +do + echo $i + clang-format -i -style="{BasedOnStyle: LLVM, + IndentWidth: 2, + UseTab: Never, + + AllowShortBlocksOnASingleLine: false, + AllowShortIfStatementsOnASingleLine: false, + AllowShortFunctionsOnASingleLine: false, + + BreakBeforeBraces: Custom, + BraceWrapping: { AfterFunction: true, + BeforeElse: true }, + + IndentCaseLabels: true, + PenaltyReturnTypeOnItsOwnLine: 0, + ColumnLimit: 120}" $i +done diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 92b5542f0..c1c97237e 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -97,7 +97,7 @@ fi if [[ " X9LITES X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITES rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES -DMULTIMODULE=NO "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -187,7 +187,7 @@ fi if [[ " T16 COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on T16 boards rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X10 -DPCBREV=T16 -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X10 -DPCBREV=T16 -DHELI=YES -DLUA=YES -DGVARS=YES -DAFHDS3=NO "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -205,7 +205,7 @@ fi if [[ " X12S COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X12S rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X12S -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X12S -DHELI=YES -DLUA=YES -DGVARS=YES -DMULTIMODULE=NO "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio