diff --git a/DONATIONS.txt b/DONATIONS.txt index 2f8a9e743..ad2efa2db 100644 --- a/DONATIONS.txt +++ b/DONATIONS.txt @@ -317,3 +317,4 @@ Arold Reinders Robert Miller Aviomotive - www.aviomotive.com Mark Gaskievicz +Roland Müller diff --git a/companion/src/customizesplashdialog.cpp b/companion/src/customizesplashdialog.cpp index 070fe3dc0..3b8240f6c 100644 --- a/companion/src/customizesplashdialog.cpp +++ b/companion/src/customizesplashdialog.cpp @@ -7,19 +7,128 @@ #include "splashlibrary.h" #include "flashinterface.h" +//*** Side Class *** + Side::Side(){ imageLabel = 0; fileNameEdit = 0; saveButton = 0; - source=new Source; - *source = UNDEFINED; + saveToFileName = new QString(""); + source = new Source(UNDEFINED); } -void Side::copyImage( Side side ){ - if ((*source!=UNDEFINED) && (*side.source!=UNDEFINED)) +void Side::copyImage( Side side ) +{ + if ((*source!=UNDEFINED) && (*side.source!=UNDEFINED)) imageLabel->setPixmap(*side.imageLabel->pixmap()); } +bool Side::displayImage( QString fileName, Source pictSource ) +{ + QImage image; + + if (fileName.isEmpty()) { + return false; + } + if (pictSource == FW ){ + FlashInterface flash(fileName); + if (!flash.hasSplash()) + return false; + else + image = flash.getSplash(); + } + else { + image.load(fileName); + } + if (image.isNull()) { + return false; + } + if (imageLabel->width()==424) { + image=image.convertToFormat(QImage::Format_RGB32); + QRgb col; + int gray; + int width = image.width(); + int height = image.height(); + for (int i = 0; i < width; ++i) { + for (int j = 0; j < height; ++j) { + col = image.pixel(i, j); + gray = qGray(col); + image.setPixel(i, j, qRgb(gray, gray, gray)); + } + } + imageLabel->setPixmap(QPixmap::fromImage(image.scaled(imageLabel->width()/2, imageLabel->height()/2))); + } + else { + imageLabel->setPixmap(QPixmap::fromImage(image.scaled(imageLabel->width()/2, imageLabel->height()/2).convertToFormat(QImage::Format_Mono))); + } + switch (pictSource){ + case FW: + fileNameEdit->setText(QObject::tr("FW: %1").arg(fileName)); + *saveToFileName = fileName; + *source=FW; + break; + case PICT: + fileNameEdit->setText(QObject::tr("Pict: %1").arg(fileName)); + *saveToFileName = fileName; + *source=PICT; + break; + case PROFILE: + fileNameEdit->setText(QObject::tr("Profile image")); + *saveToFileName = fileName; + *source=PROFILE; + break; + default: + break; + } + saveButton->setEnabled(true); + libraryButton->setEnabled(true); + invertButton->setEnabled(true); + return true; +} + +bool Side::refreshImage() +{ + return displayImage( *saveToFileName, *source ); +} + +bool Side::saveImage() +{ + QSettings settings; + + if (*source == FW ) + { + FlashInterface flash(*saveToFileName); + if (!flash.hasSplash()) { + return false; + } + QImage image = imageLabel->pixmap()->toImage().scaled(flash.getSplashWidth(), flash.getSplashHeight()); + if (flash.setSplash(image) && (flash.saveFlash(*saveToFileName) > 0)) { + settings.setValue("lastFlashDir", QFileInfo(*saveToFileName).dir().absolutePath()); + } + else { + return false; + } + } + else if (*source == PICT) { + QImage image = imageLabel->pixmap()->toImage().scaled(imageLabel->width()/2, imageLabel->height()/2).convertToFormat(QImage::Format_Indexed8); + if (image.save(*saveToFileName)) { + settings.setValue("lastImagesDir", QFileInfo(*saveToFileName).dir().absolutePath()); + } + else { + return false; + } + } + else if (*source == PROFILE) { + QImage image = imageLabel->pixmap()->toImage().scaled(imageLabel->width()/2, imageLabel->height()/2).convertToFormat(QImage::Format_Indexed8); + if (!image.save(*saveToFileName)) { + return false; + } + } + return true; +} + +//*** customizeSplashDialog Class *** + customizeSplashDialog::customizeSplashDialog(QWidget *parent) : QDialog(parent), ui(new Ui::customizeSplashDialog) @@ -39,6 +148,7 @@ customizeSplashDialog::customizeSplashDialog(QWidget *parent) : left.invertButton = ui->leftInvertButton; right.invertButton = ui->rightInvertButton; + loadProfile(left); resize(0,0); } @@ -62,25 +172,10 @@ void customizeSplashDialog::loadFirmware(Side side) QSettings settings; QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), settings.value("lastFlashDir").toString(), FLASH_FILES_FILTER); if (!fileName.isEmpty()) { - QFile file(fileName); - if (fileName.isEmpty() || !file.exists()) - return; - - FlashInterface flash(fileName); - if (!flash.hasSplash()) { - QMessageBox::information(this, tr("Error"), tr("Could not find bitmap to replace in file")); - return; - } - - side.saveButton->setEnabled(true); - side.imageLabel->setPixmap(QPixmap::fromImage(flash.getSplash())); - side.imageLabel->setFixedSize(flash.getSplashWidth()*2,flash.getSplashHeight()*2); - side.fileNameEdit->setText(fileName); + if (!side.displayImage( fileName, FW )) + QMessageBox::critical(this, tr("Error"), tr("Cannot load embedded FW image from %1.").arg(fileName)); + else settings.setValue("lastFlashDir", QFileInfo(fileName).dir().absolutePath()); - *side.source=FW; - side.saveButton->setEnabled(true); - side.libraryButton->setEnabled(true); - side.invertButton->setEnabled(true); } } @@ -96,46 +191,25 @@ void customizeSplashDialog::loadPicture(Side side) QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image to load"), settings.value("lastImagesDir").toString(), tr("Images (%1)").arg(supportedImageFormats)); - if (fileName.isEmpty()){ - return; + if (!fileName.isEmpty()) { + if (!side.displayImage( fileName, PICT )) + QMessageBox::critical(this, tr("Error"), tr("Cannot load the image file %1.").arg(fileName)); + else + settings.setValue("lastImagesDir", QFileInfo(fileName).dir().absolutePath()); } - QImage image(fileName); - if (image.isNull()) { - QMessageBox::critical(this, tr("Error"), tr("Cannot load %1.").arg(fileName)); - return; - } - if (side.imageLabel->width()==424) { - image=image.convertToFormat(QImage::Format_RGB32); - QRgb col; - int gray; - int width = image.width(); - int height = image.height(); - for (int i = 0; i < width; ++i) - { - for (int j = 0; j < height; ++j) - { - col = image.pixel(i, j); - gray = qGray(col); - image.setPixel(i, j, qRgb(gray, gray, gray)); - } - } - side.imageLabel->setPixmap(QPixmap::fromImage(image.scaled(side.imageLabel->width()/2, side.imageLabel->height()/2))); - } else { - side.imageLabel->setPixmap(QPixmap::fromImage(image.scaled(side.imageLabel->width()/2, side.imageLabel->height()/2).convertToFormat(QImage::Format_Mono))); - } - - settings.setValue("lastImagesDir", QFileInfo(fileName).dir().absolutePath()); - side.fileNameEdit->setText(fileName); - *side.source=PICT; - side.saveButton->setEnabled(true); - side.libraryButton->setEnabled(true); - side.invertButton->setEnabled(true); } void customizeSplashDialog::on_leftLoadProfileButton_clicked() {loadProfile(left);} void customizeSplashDialog::on_rightLoadProfileButton_clicked() {loadProfile(right);} void customizeSplashDialog::loadProfile(Side side) { + QSettings settings; + QString fileName=settings.value("SplashFileName","").toString(); + + if (!fileName.isEmpty()) { + if (!side.displayImage( fileName, PROFILE )) + QMessageBox::critical(this, tr("Error"), tr("Cannot load the profile image %1.").arg(fileName)); + } } void customizeSplashDialog::on_leftLibraryButton_clicked(){libraryButton_clicked(left);} @@ -143,67 +217,26 @@ void customizeSplashDialog::on_rightLibraryButton_clicked(){libraryButton_clicke void customizeSplashDialog::libraryButton_clicked( Side side ) { QString fileName; - splashLibrary *ld = new splashLibrary(this,&fileName); ld->exec(); if (!fileName.isEmpty()) { - QImage image(fileName); - if (image.isNull()) { - QMessageBox::critical(this, tr("Error"), tr("Cannot load %1.").arg(fileName)); - return; - } - if (side.imageLabel->width()==424) { - image=image.convertToFormat(QImage::Format_RGB32); - QRgb col; - int gray; - int width = image.width(); - int height = image.height(); - for (int i = 0; i < width; ++i) - { - for (int j = 0; j < height; ++j) - { - col = image.pixel(i, j); - gray = qGray(col); - image.setPixel(i, j, qRgb(gray, gray, gray)); - } - } - side.imageLabel->setPixmap(QPixmap::fromImage(image.scaled(side.imageLabel->width()/2, side.imageLabel->height()/2))); - } else { - side.imageLabel->setPixmap(QPixmap::fromImage(image.scaled(side.imageLabel->width()/2, side.imageLabel->height()/2).convertToFormat(QImage::Format_Mono))); - } + if (!side.displayImage( fileName, UNDEFINED )) + QMessageBox::critical(this, tr("Error"), tr("Cannot load the library image %1.").arg(fileName)); } } void customizeSplashDialog::on_leftSaveButton_clicked(){saveButton_clicked(left);} void customizeSplashDialog::on_rightSaveButton_clicked(){saveButton_clicked(right);} -void customizeSplashDialog::saveButton_clicked(Side side) +void customizeSplashDialog::saveButton_clicked( Side side ) { - QSettings settings; - QString fileName = side.fileNameEdit->text(); - - if (*side.source == FW) - { - FlashInterface flash(fileName); - if (!flash.hasSplash()) { - QMessageBox::critical(this, tr("Error"), tr("Could not store image in firmware file %1").arg(fileName)); - return; - } - QImage image = side.imageLabel->pixmap()->toImage().scaled(flash.getSplashWidth(), flash.getSplashHeight()); - if (flash.setSplash(image) && (flash.saveFlash(fileName) > 0)) - settings.setValue("lastFlashDir", QFileInfo(fileName).dir().absolutePath()); - else - QMessageBox::critical(this, tr("Error"), tr("Could not store image in firmware file %1").arg(fileName)); - } - else if (*side.source == PICT) - { - if (!fileName.isEmpty()) { - QImage image = side.imageLabel->pixmap()->toImage().scaled(side.imageLabel->width()/2, side.imageLabel->height()/2).convertToFormat(QImage::Format_Indexed8); - if (image.save(fileName)) - settings.setValue("lastImagesDir", QFileInfo(fileName).dir().absolutePath()); - else - QMessageBox::critical(this, tr("Error"), tr("The image file %1 could not be stored").arg(fileName)); + if (side.saveImage()){ + QMessageBox::information(this, tr("File Saved"), tr("The image was saved to the file %1").arg(*side.saveToFileName)); + if ( !side.refreshImage()){ + QMessageBox::critical(this, tr("Image Refresh Error"), tr("Failed to refresh image from file %1").arg(*side.saveToFileName)); } } + else + QMessageBox::critical(this, tr("File Save Error"), tr("Failed to write image to %1").arg(*side.saveToFileName)); } void customizeSplashDialog::on_leftInvertButton_clicked(){invertButton_clicked(left);} diff --git a/companion/src/customizesplashdialog.h b/companion/src/customizesplashdialog.h index 8ae954d1c..b4db9a60e 100644 --- a/companion/src/customizesplashdialog.h +++ b/companion/src/customizesplashdialog.h @@ -17,6 +17,9 @@ class Side public: Side(); void copyImage( Side ); + bool displayImage( QString fileName, Source source ); + bool saveImage(); + bool refreshImage(); QLabel *imageLabel; QLineEdit *fileNameEdit; @@ -24,6 +27,9 @@ public: QPushButton *invertButton; QToolButton *libraryButton; + QString *saveToFileName; + +private: Source *source; }; diff --git a/companion/src/customizesplashdialog.ui b/companion/src/customizesplashdialog.ui index b98d87907..fa6c57d9f 100644 --- a/companion/src/customizesplashdialog.ui +++ b/companion/src/customizesplashdialog.ui @@ -254,6 +254,16 @@ + + + + true + + + Load Profile + + + @@ -268,16 +278,6 @@ - - - - false - - - Load Profile - - - @@ -550,6 +550,16 @@ + + + + true + + + Load Profile + + + @@ -567,16 +577,6 @@ - - - - false - - - Load Profile - - - @@ -625,12 +625,17 @@ leftFileNameEdit leftInvertButton + leftLibraryButton + leftLoadProfileButton + leftLoadFwButton leftLoadPictButton leftSaveButton copyLeftToRightButton copyRightToLeftButton rightFileNameEdit rightInvertButton + rightLibraryButton + rightLoadProfileButton rightLoadFwButton rightLoadPictButton rightSaveButton diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h index 06c9ec13f..4c5780b82 100644 --- a/companion/src/eeprominterface.h +++ b/companion/src/eeprominterface.h @@ -883,8 +883,12 @@ class ModelData { SwashRingData swashRingData; unsigned int thrTraceSrc; int8_t traineron; // 0 disable trainer, 1 allow trainer - unsigned int modelId; + unsigned int modelId; unsigned int switchWarningStates; + unsigned int nSwToWarn; + unsigned int nPotsToWarn; + int potPosition[C9X_NUM_POTS]; + bool displayText; // TODO structure char gvars_names[C9X_MAX_GVARS][6+1]; bool gvars_popups[C9X_MAX_GVARS]; @@ -1030,6 +1034,7 @@ enum Capability { CSFunc, LCDWidth, GetThrSwitch, + HasDisplayText, VirtualInputs, LuaInputs, LimitsPer1000, diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index b36ed2c50..e4056d696 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -24,13 +24,13 @@ #define MAX_CURVES(board, version) (IS_ARM(board) ? ((IS_TARANIS(board) && version >= 216) ? 32 : 16) : O9X_MAX_CURVES) #define MAX_GVARS(board, version) ((IS_ARM(board) && version >= 216) ? 9 : 5) -#define IS_RELEASE_21_MARCH_2013(board, version) (version >= 214 || (!IS_ARM(board) && version >= 213)) -#define IS_RELEASE_23_MARCH_2013(board, version) (version >= 214 || (board==BOARD_STOCK && version >= 213)) +#define IS_AFTER_RELEASE_21_MARCH_2013(board, version) (version >= 214 || (!IS_ARM(board) && version >= 213)) +#define IS_AFTER_RELEASE_23_MARCH_2013(board, version) (version >= 214 || (board==BOARD_STOCK && version >= 213)) inline int switchIndex(int i, BoardEnum board, unsigned int version) { - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); - if (!IS_TARANIS(board) && release21March2013) + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); + if (!IS_TARANIS(board) && afterrelease21March2013) return (i<=3 ? i+3 : (i<=6 ? i-3 : i)); else return i; @@ -153,7 +153,7 @@ class SourcesConversionTable: public ConversionTable { public: SourcesConversionTable(BoardEnum board, unsigned int version, unsigned int variant, unsigned long flags=0) { - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); int val=0; @@ -177,19 +177,19 @@ class SourcesConversionTable: public ConversionTable { for (int i=0; i(mix.name)); } } - else if (IS_DBLRAM(board, version) && IS_RELEASE_23_MARCH_2013(board, version)) { + else if (IS_DBLRAM(board, version) && IS_AFTER_RELEASE_23_MARCH_2013(board, version)) { internalField.Append(new UnsignedField<4>(_destCh)); internalField.Append(new BoolField<1>(_curveMode)); internalField.Append(new BoolField<1>(mix.noExpo)); @@ -849,7 +849,7 @@ class ExpoField: public TransformedField { } internalField.Append(new SignedField<8>(_curveParam)); } - else if (IS_DBLRAM(board, version) && IS_RELEASE_23_MARCH_2013(board, version)) { + else if (IS_DBLRAM(board, version) && IS_AFTER_RELEASE_23_MARCH_2013(board, version)) { internalField.Append(new UnsignedField<2>(expo.mode)); internalField.Append(new UnsignedField<2>(expo.chn)); internalField.Append(new BoolField<1>(_curveMode)); @@ -1051,9 +1051,9 @@ class LogicalSwitchesFunctionsTable: public ConversionTable { LogicalSwitchesFunctionsTable(BoardEnum board, unsigned int version) { int val=0; - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); addConversion(LS_FN_OFF, val++); - if (release21March2013) + if (afterrelease21March2013) addConversion(LS_FN_VEQUAL, val++); addConversion(LS_FN_VPOS, val++); addConversion(LS_FN_VNEG, val++); @@ -1065,11 +1065,11 @@ class LogicalSwitchesFunctionsTable: public ConversionTable { addConversion(LS_FN_XOR, val++); if (IS_ARM(board) && version >= 216) addConversion(LS_FN_STAY, val++); addConversion(LS_FN_EQUAL, val++); - if (!release21March2013) + if (!afterrelease21March2013) addConversion(LS_FN_NEQUAL, val++); addConversion(LS_FN_GREATER, val++); addConversion(LS_FN_LESS, val++); - if (!release21March2013) { + if (!afterrelease21March2013) { addConversion(LS_FN_EGREATER, val++); addConversion(LS_FN_ELESS, val++); } @@ -1371,20 +1371,17 @@ class SwitchesWarningField: public TransformedField { virtual void beforeExport() { - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); - if (release21March2013) { - _sw = (sw & 0xC1) + ((sw & 0x30) >> 3) + ((sw & 0x0E) << 2); - } - else { _sw = sw; - } } virtual void afterImport() { - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); - if (release21March2013) { - sw = (_sw & 0xC1) + ((_sw & 0x38) >> 2) + ((_sw & 0x06) << 3); + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); + if (afterrelease21March2013 && version < 216) { + sw = _sw >> 1; + } + else if (!afterrelease21March2013) { + sw = ((_sw & 0x30) >> 4) + ((_sw & 0x0E) << 1) + ((_sw & 0xC0) >> 1); } else { sw = _sw; @@ -1784,8 +1781,8 @@ class FrskyScreenField: public DataField { { _screen = screen; - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); - if (!release21March2013) { + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); + if (!afterrelease21March2013) { for (int i=0; i<4; i++) { if (_screen.body.bars[i].source > 0) _screen.body.bars[i].source--; @@ -1809,12 +1806,12 @@ class FrskyScreenField: public DataField { { _screen = screen; - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); // NOTA: screen.type should have been imported first! if (screen.type == 0) { numbers.ImportBits(input); - if (!release21March2013) { + if (!afterrelease21March2013) { int columns=(IS_TARANIS(board) ? 3:2); for (int i=0; i<4; i++) { for (int j=0; j 0) _screen.body.bars[i].source++; @@ -2016,9 +2013,9 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u else internalField.Append(new ZCharField<10>(modelData.name)); - bool release21March2013 = IS_RELEASE_21_MARCH_2013(board, version); + bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version); - if (release21March2013) + if (afterrelease21March2013) internalField.Append(new UnsignedField<8>(modelData.modelId)); if (IS_TARANIS(board) && version >= 215) { @@ -2035,7 +2032,7 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u internalField.Append(new SpareBitsField<4>()); internalField.Append(new SignedField<16>(modelData.timers[i].pvalue)); } - else if (release21March2013) { + else if (afterrelease21March2013) { internalField.Append(new UnsignedField<12>(modelData.timers[i].val)); internalField.Append(new BoolField<1>((bool &)modelData.timers[i].countdownBeep)); internalField.Append(new BoolField<1>(modelData.timers[i].minuteBeep)); @@ -2077,7 +2074,7 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u internalField.Append(new BoolField<1>(modelData.disableThrottleWarning)); if (IS_TARANIS(board) || (IS_ARM(board) && version >= 216)) - internalField.Append(new SpareBitsField<1>()); + internalField.Append(new BoolField<1>(modelData.displayText)); else internalField.Append(new BoolField<1>(modelData.moduleData[0].ppmPulsePol)); @@ -2119,15 +2116,19 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u internalField.Append(new UnsignedField<8>(modelData.thrTraceSrc)); - if (!release21March2013) { + if (!afterrelease21March2013) { internalField.Append(new UnsignedField<8>(modelData.modelId)); } if (IS_TARANIS(board)) - internalField.Append(new UnsignedField<16>(modelData.switchWarningStates)); + internalField.Append(new SwitchesWarningField<16>(modelData.switchWarningStates, board, version)); else internalField.Append(new SwitchesWarningField<8>(modelData.switchWarningStates, board, version)); + if (version >= 216) { + internalField.Append(new UnsignedField<8>(modelData.nSwToWarn)); + } + if ((board == BOARD_STOCK || (board == BOARD_M128 && version >= 215)) && (variant & GVARS_VARIANT)) { for (int i=0; i= 216) { + internalField.Append(new UnsignedField<8>(modelData.nPotsToWarn)); + for (int i=0; i < GetEepromInterface()->getCapability(Pots); i++) { + internalField.Append(new SignedField<8>(modelData.potPosition[i])); + } + } + if (IS_TARANIS(board)) { for (int i=0; i(modelData.curves[i].name)); @@ -2189,6 +2197,10 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u internalField.Append(new SpareBitsField<720>()); for (int i=0; i<32; i++) internalField.Append(new ZCharField<4>(modelData.inputNames[i])); + internalField.Append(new UnsignedField<8>(modelData.nPotsToWarn)); + for (int i=0; i < GetEepromInterface()->getCapability(Pots); i++) { + internalField.Append(new SignedField<8>(modelData.potPosition[i])); + } } } diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index fd79fbaa1..16dbfeca9 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -671,6 +671,7 @@ int Open9xInterface::getCapability(const Capability capability) return (IS_TARANIS(board) ? 212 : 128) ; case GetThrSwitch: return (IS_TARANIS(board) ? DSW_SF1 : DSW_THR) ; + case HasDisplayText: case VirtualInputs: return IS_TARANIS(board) ? 32 : 0; case LuaInputs: diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index d9f00b7f2..4a134983f 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -1829,6 +1829,9 @@ void MainWindow::createActions() connect(profileActs[i], SIGNAL(triggered()), this, SLOT(loadProfile())); } updateProfilesActions(); + createProfileAct = new QAction(tr("New Profile"), this); + createProfileAct->setStatusTip(tr("Create a new Radio Setting Profile")); + connect(createProfileAct, SIGNAL(triggered()), this, SLOT(createProfile())); classicThemeAct = new QAction(tr("Classic"), this); classicThemeAct->setStatusTip(tr("The multicolor classical Companion icon theme")); @@ -1913,7 +1916,6 @@ void MainWindow::createMenus() { QMenu *recentFileMenu=new QMenu(tr("Recent Files")); - QMenu *profilesMenu=new QMenu(tr("Firmware Profiles")); QMenu *languageMenu=new QMenu(tr("Set Menu Language")); QMenu *themeMenu=new QMenu(tr("Set Icon Theme")); QMenu *iconThemeSizeMenu=new QMenu(tr("Set Icon Size")); @@ -1935,11 +1937,7 @@ void MainWindow::createMenus() fileMenu->addAction(compareAct); fileMenu->addSeparator(); fileMenu->addAction(fwPreferencesAct); - fileMenu->addMenu(profilesMenu); - - profilesMenu->setIcon(CompanionIcon("profiles.png")); - for (int i=0; iaddAction(profileActs[i]); + fileMenu->addMenu(createProfilesMenu()); fileMenu->addAction(exitAct); editMenu = menuBar()->addMenu(tr("&Edit")); @@ -2016,9 +2014,11 @@ QMenu *MainWindow::createRecentFileMenu() QMenu *MainWindow::createProfilesMenu() { - QMenu *profilesMenu = new QMenu(this); + QMenu *profilesMenu=new QMenu(tr("Radio Settings Profiles")); for ( int i = 0; i < MAX_PROFILES; ++i) profilesMenu->addAction(profileActs[i]); + profilesMenu->addAction(createProfileAct); + profilesMenu->setIcon(CompanionIcon("profiles.png")); return profilesMenu; } @@ -2199,9 +2199,11 @@ void MainWindow::updateProfilesActions() } settings.endGroup(); } - // separatorAct->setVisible(numRecentFiles > 0); } +void MainWindow::createProfile() +{ +} QString MainWindow::strippedName(const QString &fullFileName) { diff --git a/companion/src/mainwindow.h b/companion/src/mainwindow.h index c39e8175a..e3e082b90 100644 --- a/companion/src/mainwindow.h +++ b/companion/src/mainwindow.h @@ -150,6 +150,7 @@ private slots: void appPreferences(); void fwPreferences(); void updateMenus(); + void createProfile(); MdiChild *createMdiChild(); void setActiveSubWindow(QWidget *window); QMenu * createRecentFileMenu(); @@ -252,6 +253,7 @@ private: QAction *logsAct; QAction *recentFileActs[MAX_RECENT]; QAction *profileActs[MAX_PROFILES]; + QAction *createProfileAct; QAction *classicThemeAct; QAction *monoThemeAct; QAction *monoBlueThemeAct; diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index aa86c1275..8042ccfe3 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -392,6 +392,10 @@ Setup::Setup(QWidget *parent, ModelData & model): ui->modelImage_label->hide(); ui->imagePreview->hide(); } + + if (!GetEepromInterface()->getCapability(HasDisplayText)) { + ui->displayText->hide(); + } // Beep Center checkboxes int analogs = 4 + GetEepromInterface()->getCapability(Pots); @@ -403,14 +407,12 @@ Setup::Setup(QWidget *parent, ModelData & model): connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(onBeepCenterToggled(bool))); centerBeepCheckboxes << checkbox; } - ui->switchesStartupLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, analogs+GetEepromInterface()->getCapability(RotaryEncoders)); // Startup switches warnings - ui->switchesStartupWarning->setProperty("index", 0); - connect(ui->switchesStartupWarning, SIGNAL(currentIndexChanged(int)), this, SLOT(startupSwitchEdited(int))); for (int i=0; igetCapability(Switches)-1; i++) { - QLabel * label = new QLabel(); - QSlider * slider = new QSlider(); + QLabel * label = new QLabel(this); + QSlider * slider = new QSlider(this); + QCheckBox * cb = new QCheckBox(this); slider->setProperty("index", i+1); slider->setOrientation(Qt::Vertical); slider->setMinimum(0); @@ -429,13 +431,35 @@ Setup::Setup(QWidget *parent, ModelData & model): label->setText(switches9X[i]); slider->setMaximum(i==0 ? 2 : 1); } + cb->setProperty("index", i+1); ui->switchesStartupLayout->addWidget(label, 0, i+1); + ui->switchesStartupLayout->setAlignment(label, Qt::AlignCenter); ui->switchesStartupLayout->addWidget(slider, 1, i+1); + ui->switchesStartupLayout->setAlignment(slider, Qt::AlignCenter); + ui->switchesStartupLayout->addWidget(cb, 2, i+1); + ui->switchesStartupLayout->setAlignment(cb, Qt::AlignCenter); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(startupSwitchEdited(int))); + connect(cb, SIGNAL(toggled(bool)), this, SLOT(startupSwitchToggled(bool))); startupSwitchesSliders << slider; + startupSwitchesCheckboxes << cb; } ui->switchesStartupLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, GetEepromInterface()->getCapability(Switches)); + // Pot warnings + if(IS_TARANIS(GetEepromInterface()->getBoard())) { + for (int i=0; igetCapability(Pots); i++) { + QCheckBox * cb = new QCheckBox(this); + cb->setProperty("index", i+1); + cb->setText(AnalogString(i+4)); + ui->potWarningLayout->addWidget(cb, 0, i+1); + connect(cb, SIGNAL(toggled(bool)), this, SLOT(potWarningToggled(bool))); + potWarningCheckboxes << cb; + } + } + else { + ui->label_potWarning->hide(); + ui->potWarningMode->hide(); + } lock = false; } @@ -533,9 +557,14 @@ void Setup::update() ui->throttleTrim->setChecked(model.thrTrim); ui->extendedLimits->setChecked(model.extendedLimits); ui->extendedTrims->setChecked(model.extendedTrims); + ui->displayText->setChecked(model.displayText); updateBeepCenter(); updateStartupSwitches(); + + if(IS_TARANIS(GetEepromInterface()->getBoard())) { + updatePotWarnings(); + } for (int i=0; iupdate(); @@ -557,13 +586,13 @@ void Setup::updateStartupSwitches() lock = true; unsigned int switchStates = model.switchWarningStates; - bool enabled = !(switchStates & 0x01); - ui->switchesStartupWarning->setCurrentIndex(switchStates & 0x01); - switchStates >>= 1; for (int i=0; igetCapability(Switches)-1; i++) { QSlider * slider = startupSwitchesSliders[i]; + QCheckBox * cb = startupSwitchesCheckboxes[i]; + bool enabled = !(model.nSwToWarn & (1 << i)); slider->setEnabled(enabled); + cb->setChecked(enabled); if (IS_TARANIS(GetEepromInterface()->getBoard())) { slider->setValue(i==5 ? (switchStates & 0x3)/2 : switchStates & 0x3); switchStates >>= 2; @@ -584,36 +613,31 @@ void Setup::startupSwitchEdited(int value) unsigned int mask; int index = sender()->property("index").toInt(); - if (index == 0) { - mask = 0x01; - } - else if (IS_TARANIS(GetEepromInterface()->getBoard())) { - if (index == 6) - mask = 0x02 << (index*2 - 1); + if (IS_TARANIS(GetEepromInterface()->getBoard())) { + if (index == 6) { + shift = (index - 1) * 2; + mask = 0x02 << shift; + shift++; + } else { - shift = index*2 - 1; + shift = (index - 1) * 2; mask = 0x03 << shift; } } else { if (index == 1) { - shift = 1; - mask = 0x03 << shift; + mask = 0x03; } else { - mask = 0x01 << (index+1); + shift = index; + mask = 0x01 << shift; } } model.switchWarningStates &= ~mask; if (value) { - if (shift == 0) { - model.switchWarningStates |= mask; - } - else { - model.switchWarningStates |= (value << shift); - } + model.switchWarningStates |= (value << shift); } updateStartupSwitches(); @@ -621,6 +645,72 @@ void Setup::startupSwitchEdited(int value) } } +void Setup::startupSwitchToggled(bool checked) +{ + if (!lock) { + int index = sender()->property("index").toInt()-1; + + if (checked) + model.nSwToWarn &= ~(1 << index); + else + model.nSwToWarn |= (1 << index); + + updateStartupSwitches(); + emit modified(); + } +} + +void Setup::updatePotWarnings() +{ + lock = true; + int mode = model.nPotsToWarn >> 6; + ui->potWarningMode->setCurrentIndex(mode); + + if (mode == 0) + model.nPotsToWarn = 0x3F; + + for (int i=0; isetChecked(enabled); + potWarningCheckboxes[i]->setDisabled(mode == 0); + } + lock = false; +} + +void Setup::potWarningToggled(bool checked) +{ + if (!lock) { + int index = sender()->property("index").toInt()-1; + + if(checked) + model.nPotsToWarn &= ~(1 << index); + else + model.nPotsToWarn |= (1 << index); + + updatePotWarnings(); + emit modified(); + } +} + +void Setup::on_potWarningMode_currentIndexChanged(int index) +{ + if (!lock) { + int mask = 0xC0; + model.nPotsToWarn = model.nPotsToWarn & ~mask; + model.nPotsToWarn = model.nPotsToWarn | ((index << 6) & mask); + + updatePotWarnings(); + emit modified(); + } +} + +void Setup::on_displayText_toggled(bool checked) +{ + model.displayText = checked; + emit modified(); +} + void Setup::on_throttleTrim_toggled(bool checked) { model.thrTrim = checked; diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 9608d85a3..b785e2750 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace Ui { class Setup; @@ -82,19 +83,26 @@ class Setup : public ModelPanel void on_extendedTrims_toggled(bool checked); void on_throttleWarning_toggled(bool checked); void on_throttleReverse_toggled(bool checked); + void on_displayText_toggled(bool checked); void on_image_currentIndexChanged(int index); void on_trimIncrement_currentIndexChanged(int index); void onBeepCenterToggled(bool checked); void startupSwitchEdited(int value); + void startupSwitchToggled(bool checked); + void potWarningToggled(bool checked); + void on_potWarningMode_currentIndexChanged(int index); void onChildModified(); private: Ui::Setup *ui; QVector startupSwitchesSliders; + QVector startupSwitchesCheckboxes; + QVector potWarningCheckboxes; QVector centerBeepCheckboxes; ModulePanel * modules[C9X_NUM_MODULES+1]; TimerPanel * timers[C9X_MAX_TIMERS]; void updateStartupSwitches(); + void updatePotWarnings(); void updateBeepCenter(); }; diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui index c4a632c00..29753cdb3 100644 --- a/companion/src/modeledit/setup.ui +++ b/companion/src/modeledit/setup.ui @@ -6,8 +6,8 @@ 0 0 - 782 - 334 + 787 + 727 @@ -16,134 +16,6 @@ - - - - Model Name - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Timer2 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Timer1 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Throttle Source - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Switch startup Warning - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Center beep - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Trim Increment - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - QLayout::SetMinimumSize - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - ON - - - - - OFF - - - - - - - - - 0 - 0 - - - - Check - - - Qt::AlignCenter - - - - - @@ -231,6 +103,85 @@ + + + + Model Name + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Timer2 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Timer1 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Throttle Source + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Switch Warnings + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Center beep + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Trim Increment + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -288,6 +239,29 @@ + + + + Qt::RightToLeft + + + Display Checklist + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -353,6 +327,58 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi + + + + QLayout::SetMinimumSize + + + 0 + + + 6 + + + 6 + + + + + + + true + + + Pot Warnings + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + OFF + + + + + Manual + + + + + Auto + + + + + + diff --git a/radio/src/eeprom_conversions.cpp b/radio/src/eeprom_conversions.cpp index defef59ea..99bd2c841 100644 --- a/radio/src/eeprom_conversions.cpp +++ b/radio/src/eeprom_conversions.cpp @@ -111,6 +111,8 @@ PACK(typedef struct { }) MixData_v215; #endif + + PACK(typedef struct { int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw uint16_t start:12; @@ -474,7 +476,8 @@ void ConvertModel_215_to_216(ModelData &model) #endif } g_model.thrTraceSrc = oldModel.thrTraceSrc; - g_model.switchWarningStates = oldModel.switchWarningStates; + g_model.switchWarningStates = oldModel.switchWarningStates >> 1; + g_model.nSwToWarn = (oldModel.switchWarningStates & 0x01) ? 0xFF : 0; for (uint8_t i=0; i<5; i++) { memcpy(g_model.gvars[i].name, oldModel.gvar_names[i], LEN_GVAR_NAME); } diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index a7499aa0b..db47af0c2 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -669,7 +669,8 @@ void menuModelFailsafe(uint8_t event) bool newLongNames = false; uint8_t ch; - if (event == EVT_KEY_BREAK(KEY_ENTER) && s_editMode) { + if (event == EVT_KEY_LONG(KEY_ENTER) && s_editMode) { + s_noHi = NO_HI_LEN; g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert]; eeDirty(EE_MODEL); AUDIO_WARNING1(); @@ -721,7 +722,7 @@ void menuModelFailsafe(uint8_t event) // Value LcdFlags flags = TINSIZE; - if (m_posVert == ch) { + if (m_posVert == ch && !s_noHi) { flags |= INVERS; if (s_editMode) flags |= BLINK; @@ -873,7 +874,11 @@ enum menuModelSetupItems { ITEM_MODEL_THROTTLE_TRACE, ITEM_MODEL_THROTTLE_TRIM, ITEM_MODEL_THROTTLE_WARNING, +#if defined(PCBTARANIS) + ITEM_MODEL_CHECKLIST_DISPLAY, +#endif ITEM_MODEL_SWITCHES_WARNING, + CASE_PCBTARANIS(ITEM_MODEL_POT_WARNING) ITEM_MODEL_BEEP_CENTER, #if defined(PCBTARANIS) ITEM_MODEL_INTERNAL_MODULE_LABEL, @@ -956,21 +961,22 @@ void menuModelSetup(uint8_t event) #define PORT_CHANNELS_ROWS(x) (x==0 ? PORT1_CHANNELS_ROWS() : (x==1 ? PORT2_CHANNELS_ROWS() : TRAINER_CHANNELS_ROWS())) #define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) #define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX) + #define POT_WARN_ITEMS() ((g_model.nPotsToWarn >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0) bool CURSOR_ON_CELL = (m_posHorz >= 0); - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(IS_D8_RX(0) ? (uint8_t)1 : (uint8_t)2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_XJT(1) && IS_D8_RX(1)) ? (uint8_t)1 : (IS_MODULE_PPM(1) || IS_MODULE_XJT(1) || IS_MODULE_DSM2(1)) ? (uint8_t)2 : HIDDEN_ROW, IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, CASE_PCBTARANIS(0) 7, POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(IS_D8_RX(0) ? (uint8_t)1 : (uint8_t)2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_XJT(1) && IS_D8_RX(1)) ? (uint8_t)1 : (IS_MODULE_PPM(1) || IS_MODULE_XJT(1) || IS_MODULE_DSM2(1)) ? (uint8_t)2 : HIDDEN_ROW, IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); #elif defined(CPUM64) #define CURSOR_ON_CELL (true) #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) uint8_t protocol = g_model.protocol; - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2 }); + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2 }); #else #define CURSOR_ON_CELL (true) #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) uint8_t protocol = g_model.protocol; - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2, IF_PCBSKY9X(1) IF_PCBSKY9X(2) }); + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 6, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2, IF_PCBSKY9X(1) IF_PCBSKY9X(2) }); #endif if (!MENU_CHECK(menuTabModel, e_ModelSetup, MODEL_SETUP_MAX_LINES)) { @@ -1096,10 +1102,11 @@ void menuModelSetup(uint8_t event) g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event); #else g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 ? attr : 0); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 && !s_noHi ? attr : 0); if (attr && m_posHorz>0) { s_editMode = 0; if (event==EVT_KEY_LONG(KEY_ENTER)) { + s_noHi = NO_HI_LEN; for (uint8_t i=0; i>= 1; - for (uint8_t i=1; i>= 2; + c = "\300-\301"[states & 0x03]; + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+i*(2*FW), y, 'A'+i, line && (m_posHorz == i) ? INVERS : 0); + if (swactive) lcd_putc(MODEL_SETUP_2ND_COLUMN+i*(2*FW)+FWNUM, y, c); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+((NUM_SWITCHES-1)*2*FW+2), y, PSTR("<]"), (m_posHorz == NUM_SWITCHES-1 && !s_noHi) ? line : 0); + states >>= 2; #else - attr = 0; - if (IS_3POS(i-1)) { - c = '0'+(states & 0x03); - states >>= 2; - } - else { - if (states & 0x01) - attr = INVERS; - c = pgm_read_byte(STR_VSWITCHES - 2 + 6 + (3*i)); - states >>= 1; - } - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+2*FW+i*FW, y, c, attr); -#endif + attr = 0; + + if (IS_3POS(i)) { + c = '0'+(states & 0x03); + states >>= 2; } + else { + if ((states & 0x01) && swactive) + attr = INVERS; + c = pgm_read_byte(STR_VSWITCHES - 2 + 9 + (3*i)); + states >>= 1; + } + if (line && (m_posHorz == i)) { + attr = BLINK; + if (swactive) + attr |= INVERS; + } + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+i*FW, y, (swactive || (attr & BLINK)) ? c : '-', attr); +#if !defined(CPUM64) + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+(NUM_SWITCHES*FW), y, PSTR("<]"), (m_posHorz == NUM_SWITCHES-1 && !s_noHi) ? line : 0); +#endif +#endif } break; } +#if defined(PCBTARANIS) + case ITEM_MODEL_POT_WARNING: + { + lcd_putsLeft(y, STR_POTWARNING); + uint8_t potMode = g_model.nPotsToWarn >> 6; + if(attr) { + if (m_posHorz) s_editMode = 0; + if (!READ_ONLY() && m_posHorz) { + switch(event) { + case EVT_KEY_LONG(KEY_ENTER): + killEvents(event); + if(potMode == 1) { + g_model.potPosition[m_posHorz-1] = getValue(MIXSRC_FIRST_POT+m_posHorz-1) >> 3; + AUDIO_WARNING1(); + eeDirty(EE_MODEL); + } + break; + case EVT_KEY_BREAK(KEY_ENTER): + g_model.nPotsToWarn ^= (1 << (m_posHorz-1)); + eeDirty(EE_MODEL); + break; + } + } + } + + lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, PSTR("\004""Off\0""Man\0""Auto"), potMode, attr & ((m_posHorz == 0) ? attr : !INVERS)); + if (potMode) + for (uint8_t i=0; i> 6; + if(potMode) { + perOut(e_perout_mode_normal, 0); + bad_pots = 0; + for (uint8_t i=0; i> 3)) > 2)) { + warn = true; + bad_pots |= (1<> (i*2)]; + lcd_putcAtt(60+i*(2*FW+FW/2), 4*FH+3, 'A'+i, attr); + lcd_putcAtt(60+i*(2*FW+FW/2)+FW, 4*FH+3, c, attr); + } + } + if(potMode) { + for (uint8_t i=0; i> 3)) > 2) { + switch (i) { + case 0: + case 1: + lcd_putc(60+i*(5*FW)+2*FW+2, 6*FH-2, g_model.potPosition[i] > (getValue(MIXSRC_FIRST_POT+i) >> 3) ? 126 : 127); + break; + case 2: + case 3: + lcd_putc(60+i*(5*FW)+2*FW+2, 6*FH-2, g_model.potPosition[i] > (getValue(MIXSRC_FIRST_POT+i) >> 3) ? '\300' : '\301'); + break; + } + flags = INVERS; + } + lcd_putsiAtt(60+i*(5*FW), 6*FH-2, STR_VSRCRAW, NUM_STICKS+1+i, flags); + } + } + } + last_bad_pots = bad_pots; +#else if (last_bad_switches != switches_states) { MESSAGE(STR_SWITCHWARN, NULL, STR_PRESSANYKEYTOSKIP, last_bad_switches == 0xff ? AU_SWITCH_ALERT : AU_NONE); -#if defined(PCBTARANIS) - for (uint8_t i=0; i> (1+i*2)]; - lcd_putcAtt(60+i*(2*FW+FW/2), 5*FH, 'A'+i, attr); - lcd_putcAtt(60+i*(2*FW+FW/2)+FW, 5*FH, c, attr); - } -#else uint8_t x = 2; - for (uint8_t i=1; i2?(i+1):1+((states>>1)&0x3)), attr); - if (i == 1 && attr) i++; - if (i != 1) x += 3*FW+FW/2; + for (uint8_t i=0; i0?(i+3):(states&0x3)+1), attr); + x += 3*FW+FW/2; } #endif lcdRefresh(); @@ -4294,8 +4365,10 @@ void opentxClose() hapticOff(); #endif + saveTimers(); + #if defined(CPUARM) && defined(FRSKY) - if((g_model.frsky.mAhPersistent) && (g_model.frsky.storedMah != frskyData.hub.currentConsumption)) { + if ((g_model.frsky.mAhPersistent) && (g_model.frsky.storedMah != frskyData.hub.currentConsumption)) { g_model.frsky.storedMah = frskyData.hub.currentConsumption; eeDirty(EE_MODEL); } @@ -4305,20 +4378,24 @@ void opentxClose() } #endif - saveTimers(); - #if defined(PCBSKY9X) uint32_t mAhUsed = g_eeGeneral.mAhUsed + Current_used * (488 + g_eeGeneral.currentCalib) / 8192 / 36; - if (g_eeGeneral.mAhUsed != mAhUsed) + if (g_eeGeneral.mAhUsed != mAhUsed) { g_eeGeneral.mAhUsed = mAhUsed; + } #endif -#if defined(CPUARM) && !defined(REVA) - if (sessionTimer > 0) - g_eeGeneral.globalTimer += sessionTimer; +#if defined(PCBTARANIS) + if ((g_model.nPotsToWarn >> 6) == 2) { + for (uint8_t i=0; i> 3; + eeDirty(EE_MODEL); + } #endif g_eeGeneral.unexpectedShutdown = 0; + eeDirty(EE_GENERAL); eeCheck(true); } @@ -4909,6 +4986,12 @@ void saveTimers() } } } + +#if defined(CPUARM) && !defined(REVA) + if (sessionTimer > 0) { + g_eeGeneral.globalTimer += sessionTimer; + } +#endif } #endif diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index a5d0ba320..786c0c059 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -494,6 +494,8 @@ const pm_char STR_VIEW_TEXT[] PROGMEM = "View text"; const pm_char STR_SCALE[] PROGMEM = "Scale"; const pm_char STR_VIEW_CHANNELS[] PROGMEM = "View Channels"; const pm_char STR_VIEW_NOTES[] PROGMEM = "View Notes"; + const pm_char STR_POTWARNING[] PROGMEM = TR_POTWARNING; + const pm_char STR_CHECKLIST[] PROGMEM = TR_CHECKLIST; const pm_char STR_UART3MODE[] PROGMEM = TR_UART3MODE; const pm_char STR_POT1TYPE[] PROGMEM = TR_POT1TYPE; const pm_char STR_POT2TYPE[] PROGMEM = TR_POT2TYPE; diff --git a/radio/src/translations.h b/radio/src/translations.h index 7b60be0e1..ceeda44b7 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -682,6 +682,8 @@ extern const pm_char STR_VIEW_TEXT[]; extern const pm_char STR_SCALE[]; extern const pm_char STR_VIEW_CHANNELS[]; extern const pm_char STR_VIEW_NOTES[]; + extern const pm_char STR_POTWARNING[]; + extern const pm_char STR_CHECKLIST[]; extern const pm_char STR_UART3MODE[]; extern const pm_char STR_POT1TYPE[]; extern const pm_char STR_POT2TYPE[]; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 2dab10773..3d718ec79 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "úvodníLogo" #define TR_THROTTLEWARNING "(\043)Plyn" #define TR_SWITCHWARNING "(\043)Spínače" +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE "časové pásmo" #define TR_RXCHANNELORD TR("Pořadí kanálů", "Výchozí pořadí kanálů") #define TR_SLAVE "Podřízený" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Nízký Alarm" #define TR_CRITICALALARM INDENT "Kritický Alarm" #define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serial port" #define TR_POT1TYPE "S1 Type" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index e6097fcaa..8b0b2d5ec 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Startbild" #define TR_THROTTLEWARNING "Gas Alarm" #define TR_SWITCHWARNING TR("Sch. Alarm","Schalter Alarm") +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE TR("Zeitzone","GPS Zeit Zone") #define TR_RXCHANNELORD TR("Kanalanordnung","Kanalvoreinstellung") #define TR_SLAVE "Sch\205ler PPM1-8 als Ausgang" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Low Alarm" #define TR_CRITICALALARM INDENT "Kritisch Alarm" #define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serial port" #define TR_POT1TYPE "S1 Type" diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 292eb2e52..ed29c91a3 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Splash screen" #define TR_THROTTLEWARNING TR("T-Warning","Throttle Warning") #define TR_SWITCHWARNING TR("S-Warning","Switch Warning") +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE TR("Time Zone","GPS Time zone") #define TR_RXCHANNELORD TR("Rx Channel Ord","Default channel order") #define TR_SLAVE "Slave" @@ -611,7 +612,7 @@ #define TR_EEPROMWARN "EEPROM" #define TR_THROTTLEWARN "THROTTLE" #define TR_ALARMSWARN "ALARMS" -#define TR_SWITCHWARN "SWITCH" +#define TR_SWITCHWARN TR("SWITCH","CONTROL") #define TR_INVERT_THR TR("Invert Thr?","Invert Throttle?") #define TR_SPEAKER_VOLUME INDENT "Volume" #define TR_LCD "LCD" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Low Alarm" #define TR_CRITICALALARM INDENT "Critical Alarm" #define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serial port" #define TR_POT1TYPE "S1 Type" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index b8d954dfb..6454a1c10 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Ptalla.inicio" #define TR_THROTTLEWARNING TR("Aviso-A", "Aviso Acelerador") #define TR_SWITCHWARNING TR("Aviso-I", "Aviso Intrptor") +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE TR("Zona Hora", "GPS Zona Hora") #define TR_RXCHANNELORD TR("Rx Orden canal", "Orden habitual canales") #define TR_SLAVE "Esclavo" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Alarma baja" #define TR_CRITICALALARM INDENT "Alarma Critica" #define TR_PERSISTENT_MAH INDENT "Valor mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serial port" #define TR_POT1TYPE "S1 Type" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 57a7a9c22..d568e0ccb 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Logo d'accueil" #define TR_THROTTLEWARNING "Alerte gaz" #define TR_SWITCHWARNING TR("Alerte int","Alerte interrupt.") +#define TR_POTWARNING TR("Alerte pot","Alerte potentiom.") #define TR_TIMEZONE "Fuseau horaire" #define TR_RXCHANNELORD TR("Ordre voies RX","Ordre des voies préféré") #define TR_SLAVE "Elève" @@ -611,7 +612,7 @@ #define TR_EEPROMWARN "EEPROM" #define TR_THROTTLEWARN "GAZ" #define TR_ALARMSWARN "SON" -#define TR_SWITCHWARN "INTERS" +#define TR_SWITCHWARN TR("INTERS","CONTROLES") #define TR_INVERT_THR "Inverser Gaz?" #define TR_SPEAKER_VOLUME INDENT "Volume" #define TR_LCD "Afficheur" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Alarme basse" #define TR_CRITICALALARM INDENT "Alarme critique" #define TR_PERSISTENT_MAH TR(INDENT "Enr. mAh",INDENT "Enregistrer mAh") +#define TR_CHECKLIST "Afficher notes" #define TR_FAS_OFFSET TR(INDENT "Corr FAS", INDENT "Correction FAS") #define TR_UART3MODE "Port série" #define TR_POT1TYPE "Type S1" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index ec58310d9..9a5571c86 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN TR("Schermo avvio", "Schermata di avvio") #define TR_THROTTLEWARNING TR("All. Thr", "Allarme Throttle") #define TR_SWITCHWARNING TR("Avv. Int.", "Avviso Interr.") +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE "Ora locale" #define TR_RXCHANNELORD "Ordine ch RX" #define TR_SLAVE "Allievo" @@ -698,10 +699,11 @@ #define TR_LOWALARM INDENT "Allarme Basso" #define TR_CRITICALALARM INDENT "Allarme Critico" #define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serial port" #define TR_POT1TYPE "S1 Type" -#define TR_POT2TYPE "S2 Type" +#define TR_POT2TYPE "S2 Type" #if defined(MAVLINK) #define TR_MAVLINK_RC_RSSI_SCALE_LABEL "Max RSSI" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 0a40f2733..87a6a3627 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Logo ekranu" #define TR_THROTTLEWARNING "(\043)Gaz" #define TR_SWITCHWARNING "(\043)Przełącznik" +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE "Strefa czasowa" #define TR_RXCHANNELORD TR("Kolejność kanałów", "Bazowa kolejność kanałów") #define TR_SLAVE "Uczeń" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Alarm niski" #define TR_CRITICALALARM INDENT "Alarm krytyczny" #define TR_PERSISTENT_MAH INDENT "Zapisz mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Port szreg." #define TR_POT1TYPE "Typ S1" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index f38725a5b..41ac94296 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Splash screen" #define TR_THROTTLEWARNING "Avisa Acel" #define TR_SWITCHWARNING "Avisa Chav" +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE "Time Zone" #define TR_RXCHANNELORD "Ordem Canal RX" #define TR_SLAVE "Escravo" @@ -697,11 +698,12 @@ #define TR_CHANNELRANGE INDENT "Channel Range" #define TR_LOWALARM INDENT "Low Alarm" #define TR_CRITICALALARM INDENT "Critical Alarm" -#define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serial port" #define TR_POT1TYPE "S1 Type" -#define TR_POT2TYPE "S2 Type" +#define TR_POT2TYPE "S2 Type" #if defined(MAVLINK) #define TR_MAVLINK_RC_RSSI_SCALE_LABEL "Max RSSI" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 3fc70ed7d..5e117d67c 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -505,6 +505,7 @@ #define TR_SPLASHSCREEN "Startbild" #define TR_THROTTLEWARNING "Gasvarning" #define TR_SWITCHWARNING TR("Bryt.varn.","Brytarvarning") +#define TR_POTWARNING TR("Pot Warn.","Pot Warning") #define TR_TIMEZONE TR("Tidszon","GPS Tidszon") #define TR_RXCHANNELORD "Kanaler i RX" #define TR_SLAVE "Elev" @@ -698,6 +699,7 @@ #define TR_LOWALARM INDENT "Låg-alarm" #define TR_CRITICALALARM INDENT "Kritiskt alarm" #define TR_PERSISTENT_MAH INDENT "Store mAh" +#define TR_CHECKLIST "Display Checklist" #define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset") #define TR_UART3MODE "Serieporten" #define TR_POT1TYPE "S1-ratten"