From 059ea49f2fc5d7a80fc46c79ea2bc19f229ad753 Mon Sep 17 00:00:00 2001 From: bsongis Date: Mon, 11 May 2015 06:43:26 +0200 Subject: [PATCH] Fixes #2183 Failsafe settings on individual channels --- companion/src/modeledit/setup.cpp | 58 ++++++++++-- companion/src/modeledit/setup.h | 13 ++- radio/src/fonts/std/font_03x05.png | Bin 278 -> 346 bytes radio/src/gui/Taranis/lcd.cpp | 2 +- radio/src/gui/Taranis/menu_model_setup.cpp | 101 ++++++++++++++------- radio/src/myeeprom.h | 3 + radio/src/pulses/pxx_arm.cpp | 22 ++++- 7 files changed, 156 insertions(+), 43 deletions(-) diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 3ccfc8a85..e12ec95fc 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -119,6 +119,9 @@ void TimerPanel::on_name_editingFinished() /******************************************************************************/ +#define FAILSAFE_CHANNEL_HOLD 2000 +#define FAILSAFE_CHANNEL_NOPULSE 2001 + ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx): ModelPanel(parent, model, generalSettings, firmware), module(module), @@ -170,20 +173,29 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module } if (firmware->getCapability(HasFailsafe)) { - for (int i=0; i<16; i++) { + for (int i=0; isetText(QString::number(i+1)); + QComboBox * combo = new QComboBox(this); + combo->setProperty("index", i); + combo->addItem(tr("Value"), 0); + combo->addItem(tr("Hold"), FAILSAFE_CHANNEL_HOLD); + combo->addItem(tr("No Pulse"), FAILSAFE_CHANNEL_NOPULSE); QDoubleSpinBox * spinbox = new QDoubleSpinBox(this); spinbox->setMinimumSize(QSize(20, 0)); spinbox->setRange(-150, 150); spinbox->setSingleStep(0.1); spinbox->setDecimals(1); - spinbox->setValue(((double)module.failsafeChannels[i]*100)/1024); label->setProperty("index", i); spinbox->setProperty("index", i); failsafeSpins << spinbox; - ui->failsafesLayout->addWidget(label, 2*(i/8), i%8, Qt::AlignHCenter); - ui->failsafesLayout->addWidget(spinbox, 1+2*(i/8), i%8, Qt::AlignHCenter); + ui->failsafesLayout->addWidget(label, 3*(i/8), i%8, Qt::AlignHCenter); + ui->failsafesLayout->addWidget(combo, 1+3*(i/8), i%8, Qt::AlignHCenter); + ui->failsafesLayout->addWidget(spinbox, 2+3*(i/8), i%8, Qt::AlignHCenter); + failsafeGroups[i].combo = combo; + failsafeGroups[i].spinbox = spinbox; + updateFailsafe(i); + connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onFailsafeComboIndexChanged(int))); connect(spinbox, SIGNAL(valueChanged(double)), this, SLOT(onFailsafeSpinChanged(double))); } } @@ -370,12 +382,46 @@ void ModulePanel::on_failsafeMode_currentIndexChanged(int value) void ModulePanel::onFailsafeSpinChanged(double value) { if (!lock) { - int index = sender()->property("index").toInt(); - module.failsafeChannels[index] = (value*1024)/100; + int channel = sender()->property("index").toInt(); + module.failsafeChannels[channel] = (value*1024)/100; emit modified(); } } +void ModulePanel::onFailsafeComboIndexChanged(int index) +{ + if (!lock) { + lock = true; + int channel = sender()->property("index").toInt(); + module.failsafeChannels[channel] = ((QComboBox *)sender())->itemData(index).toInt(); + updateFailsafe(channel); + emit modified(); + lock = false; + } +} + +void ModulePanel::updateFailsafe(int channel) +{ + int failsafeValue = module.failsafeChannels[channel]; + QComboBox * combo = failsafeGroups[channel].combo; + QDoubleSpinBox * spinbox = failsafeGroups[channel].spinbox; + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { + combo->setCurrentIndex(1); + spinbox->setEnabled(false); + spinbox->setValue(0); + } + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + combo->setCurrentIndex(2); + spinbox->setEnabled(false); + spinbox->setValue(0); + } + else { + combo->setCurrentIndex(0); + spinbox->setEnabled(true); + spinbox->setValue(((double)failsafeValue*100)/1024); + } +} + /******************************************************************************/ SetupPanel::SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 800fb3a32..3e4b1926b 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -40,14 +40,23 @@ class TimerPanel : public ModelPanel class ModulePanel : public ModelPanel { + static const int maxChannels = 16; + + struct ChannelFailsafeWidgetsGroup { + QComboBox * combo; + QDoubleSpinBox * spinbox; + }; + Q_OBJECT public: ModulePanel(QWidget *parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx); virtual ~ModulePanel(); - virtual void update(); + protected: + void updateFailsafe(int channel); + private slots: void on_trainerMode_currentIndexChanged(int index); void on_protocol_currentIndexChanged(int index); @@ -59,6 +68,7 @@ class ModulePanel : public ModelPanel void on_ppmFrameLength_editingFinished(); void on_rxNumber_editingFinished(); void on_failsafeMode_currentIndexChanged(int value); + void onFailsafeComboIndexChanged(int index); void onFailsafeSpinChanged(double value); private: @@ -66,6 +76,7 @@ class ModulePanel : public ModelPanel int moduleIdx; Ui::Module *ui; QVector failsafeSpins; + ChannelFailsafeWidgetsGroup failsafeGroups[maxChannels]; }; class SetupPanel : public ModelPanel diff --git a/radio/src/fonts/std/font_03x05.png b/radio/src/fonts/std/font_03x05.png index 196b110fd8e1b7a7f6510643880179cdc0aa1619..6113f58551e2c7c013ec237e2b554330648ea2e4 100644 GIT binary patch delta 327 zcmV-N0l5B_0@?yIiBL{Q4GJ0x0000DNk~Le00027000052m$~A0EG~m@c;k-24YJ` zL;(K){{a7>y{D6rAs&C<1qTy30BUa|00000=Sf6CR7l6oR?!XvAqbPp{{NTRgNbQc ztZsM7>BEI6!&aayGP51FBBG<}MntI3Y~QT=ObJi7$4&`J{ryo%TsO-d|4;+1a-rW| zXBI?6;EQx7!ywLhiau&QRS+g6gs1x;fN|=9QMu?{=JsW9(=&gWdA*f*%=)seQ90YJwVibCh5$t8$bQGE)8w%w7BZ*7CR@mJ4Z5v(z+W?%!)v7hCXl zfil7U`>B z%#r$hamTeQ`=;@8?|l1db!C=6*Mm>h6+3=pKS{pwae9cUad7H`|BN<4zaIJKm_``i ZU()r{=>7y{RiFnLJYD@<);T3K0RUq=ZIb{1 diff --git a/radio/src/gui/Taranis/lcd.cpp b/radio/src/gui/Taranis/lcd.cpp index e41ab8ed2..829b01a95 100755 --- a/radio/src/gui/Taranis/lcd.cpp +++ b/radio/src/gui/Taranis/lcd.cpp @@ -187,7 +187,7 @@ void lcd_putcAtt(coord_t x, coord_t y, const unsigned char c, LcdFlags flags) lcdPutPattern(x, y, q, 5, 6, flags); } else if (fontsize == TINSIZE) { - q = &font_3x5[((uint16_t)c-0x2d)*3]; + q = &font_3x5[((uint16_t)c-0x20)*3]; lcdPutPattern(x, y, q, 3, 5, flags); } #if defined(BOLD_FONT) diff --git a/radio/src/gui/Taranis/menu_model_setup.cpp b/radio/src/gui/Taranis/menu_model_setup.cpp index fa0986b74..2c27e83e6 100644 --- a/radio/src/gui/Taranis/menu_model_setup.cpp +++ b/radio/src/gui/Taranis/menu_model_setup.cpp @@ -104,7 +104,7 @@ enum menuModelSetupItems { #define MODEL_SETUP_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH-1) #define MODEL_SETUP_BIND_OFS 3*FW-2 #define MODEL_SETUP_RANGE_OFS 7*FW -#define MODEL_SETUP_SET_FAILSAFE_OFS 10*FW +#define MODEL_SETUP_SET_FAILSAFE_OFS 10*FW-2 void copySelection(char *dst, const char *src, uint8_t size) { @@ -778,12 +778,27 @@ void menuModelFailsafe(uint8_t event) bool newLongNames = false; uint8_t ch = 0; - 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(); - SEND_FAILSAFE_NOW(g_moduleIdx); + if (event == EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + event = 0; + if (s_editMode) { + g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert]; + eeDirty(EE_MODEL); + AUDIO_WARNING1(); + SEND_FAILSAFE_NOW(g_moduleIdx); + } + else { + int16_t & failsafe = g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert]; + if (failsafe < FAILSAFE_CHANNEL_HOLD) + failsafe = FAILSAFE_CHANNEL_HOLD; + else if (failsafe == FAILSAFE_CHANNEL_HOLD) + failsafe = FAILSAFE_CHANNEL_NOPULSE; + else + failsafe = channelOutputs[m_posVert]; + eeDirty(EE_MODEL); + AUDIO_WARNING1(); + SEND_FAILSAFE_NOW(g_moduleIdx); + } } SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT); @@ -795,28 +810,30 @@ void menuModelFailsafe(uint8_t event) // Column separator lcd_vline(LCD_W/2, FH, LCD_H-FH); - if (m_posVert > 16) { + if (m_posVert >= 16) { ch = 16; } lcd_putsCenter(0*FH, FAILSAFESET); lcd_invert_line(0); + unsigned int lim = g_model.extendedLimits ? 640*2 : 512*2; + for (uint8_t col=0; col<2; col++) { coord_t x = col*COL_W+1; // Channels for (uint8_t line=0; line<8; line++) { coord_t y = 9+line*7; - int32_t val; + int32_t channelValue = channelOutputs[ch]; + int32_t failsafeValue = 0; + bool failsafeEditable = false; uint8_t ofs = (col ? 0 : 1); - if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) - val = 0; - else if (s_editMode && m_posVert == ch) - val = channelOutputs[ch]; - else - val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; + if (ch >= g_model.moduleData[g_moduleIdx].channelsStart && ch < NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) { + failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; + failsafeEditable = true; + } // Channel name if present, number if not uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); @@ -831,31 +848,53 @@ void menuModelFailsafe(uint8_t event) // Value LcdFlags flags = TINSIZE; - if (m_posVert == ch && !s_noHi) { + if (m_posVert == ch) { flags |= INVERS; - if (s_editMode) - flags |= BLINK; + if (s_editMode) { + if (!failsafeEditable || failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + s_editMode = 0; + } + else { + flags |= BLINK; + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim); + } + } } -#if defined(PPM_UNIT_US) - uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W); - lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags); -#elif defined(PPM_UNIT_PERCENT_PREC1) + +#if defined(PPM_UNIT_PERCENT_PREC1) uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6); - lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags); #else uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W); - lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags); #endif + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { + lcd_putsAtt(x+COL_W-4-wbar-ofs-16, y, "HOLD", flags); + failsafeValue = 0; + } + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + lcd_putsAtt(x+COL_W-4-wbar-ofs-16, y, "NONE", flags); + failsafeValue = 0; + } + else { +#if defined(PPM_UNIT_US) + lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags); +#elif defined(PPM_UNIT_PERCENT_PREC1) + lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue), PREC1|flags); +#else + lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue)/10, flags); +#endif + } + // Gauge lcd_rect(x+COL_W-3-wbar-ofs, y, wbar+1, 6); - uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2; - uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); - coord_t x0 = (val>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-len; - lcd_hline(x0, y+1, len); - lcd_hline(x0, y+2, len); - lcd_hline(x0, y+3, len); - lcd_hline(x0, y+4, len); + unsigned int lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); + unsigned int lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); + coord_t xChannel = (channelValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenChannel; + coord_t xFailsafe = (failsafeValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenFailsafe; + lcd_hlineStip(xChannel, y+1, lenChannel, DOTTED, 0); + lcd_hlineStip(xChannel, y+2, lenChannel, DOTTED, 0); + lcd_hline(xFailsafe, y+3, lenFailsafe); + lcd_hline(xFailsafe, y+4, lenFailsafe); ch++; } diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 083c09c6d..715f8d0fb 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -406,6 +406,9 @@ enum BeeperMode { #define EXTRA_GENERAL_FIELDS #endif +#define FAILSAFE_CHANNEL_HOLD 2000 +#define FAILSAFE_CHANNEL_NOPULSE 2001 + #if defined(PCBSKY9X) && defined(REVX) PACK(typedef struct { int8_t rfProtocol; diff --git a/radio/src/pulses/pxx_arm.cpp b/radio/src/pulses/pxx_arm.cpp index b73e01b78..c216fffe7 100644 --- a/radio/src/pulses/pxx_arm.cpp +++ b/radio/src/pulses/pxx_arm.cpp @@ -230,10 +230,24 @@ void setupPulsesPXX(unsigned int port) chan = (i < sendUpperChannels ? 2048 : 0); } else { - if (i < sendUpperChannels) - chan = limit(2049, PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (g_model.moduleData[port].failsafeChannels[8+g_model.moduleData[port].channelsStart+i] * 512 / 682) + 3072, 4094); - else - chan = limit(1, PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (g_model.moduleData[port].failsafeChannels[g_model.moduleData[port].channelsStart+i] * 512 / 682) + 1024, 2046); + if (i < sendUpperChannels) { + int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[8+g_model.moduleData[port].channelsStart+i]; + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) + chan = 4095; + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) + chan = 2048; + else + chan = limit(2049, PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (failsafeValue * 512 / 682) + 3072, 4094); + } + else { + int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[g_model.moduleData[port].channelsStart+i]; + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) + chan = 2047; + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) + chan = 0; + else + chan = limit(1, PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (failsafeValue * 512 / 682) + 1024, 2046); + } } } else {