diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h index 35a03e197..a75f6e80b 100644 --- a/companion/src/eeprominterface.h +++ b/companion/src/eeprominterface.h @@ -684,9 +684,9 @@ class FlightModeData { class SwashRingData { // Swash Ring data public: SwashRingData() { clear(); } - bool invertELE; - bool invertAIL; - bool invertCOL; + int elevatorWeight; + int aileronWeight; + int collectiveWeight; unsigned int type; RawSource collectiveSource; RawSource aileronSource; diff --git a/companion/src/modeledit/heli.cpp b/companion/src/modeledit/heli.cpp index 25dea72a5..53d6541f9 100644 --- a/companion/src/modeledit/heli.cpp +++ b/companion/src/modeledit/heli.cpp @@ -8,12 +8,32 @@ HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & gener { ui->setupUi(this); - connect(ui->swashTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); - connect(ui->swashCollectiveCB, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); - connect(ui->swashRingValSB, SIGNAL(editingFinished()), this, SLOT(edited())); - connect(ui->swashInvertELE, SIGNAL(stateChanged(int)), this, SLOT(edited())); - connect(ui->swashInvertAIL, SIGNAL(stateChanged(int)), this, SLOT(edited())); - connect(ui->swashInvertCOL, SIGNAL(stateChanged(int)), this, SLOT(edited())); + connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); + connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited())); + connect(ui->swashCollectiveSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); + if (firmware->getCapability(VirtualInputs)) { + connect(ui->swashAileronSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); + connect(ui->swashElevatorSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); + connect(ui->swashAileronWeight, SIGNAL(editingFinished()), this, SLOT(edited())); + connect(ui->swashElevatorWeight, SIGNAL(editingFinished()), this, SLOT(edited())); + connect(ui->swashCollectiveWeight, SIGNAL(editingFinished()), this, SLOT(edited())); + ui->invertLabel->hide(); + ui->swashElevatorInvert->hide(); + ui->swashAileronInvert->hide(); + ui->swashCollectiveInvert->hide(); + } + else { + connect(ui->swashElevatorInvert, SIGNAL(stateChanged(int)), this, SLOT(edited())); + connect(ui->swashAileronInvert, SIGNAL(stateChanged(int)), this, SLOT(edited())); + connect(ui->swashCollectiveInvert, SIGNAL(stateChanged(int)), this, SLOT(edited())); + ui->aileronLabel->hide(); + ui->elevatorLabel->hide(); + ui->swashAileronSource->hide(); + ui->swashElevatorSource->hide(); + ui->swashAileronWeight->hide(); + ui->swashElevatorWeight->hide(); + ui->swashCollectiveWeight->hide(); + } disableMouseScrolling(); } @@ -27,12 +47,21 @@ void HeliPanel::update() { lock = true; - ui->swashTypeCB->setCurrentIndex(model->swashRingData.type); - populateSourceCB(ui->swashCollectiveCB, model->swashRingData.collectiveSource, model, POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS); - ui->swashRingValSB->setValue(model->swashRingData.value); - ui->swashInvertELE->setChecked(model->swashRingData.invertELE); - ui->swashInvertAIL->setChecked(model->swashRingData.invertAIL); - ui->swashInvertCOL->setChecked(model->swashRingData.invertCOL); + ui->swashType->setCurrentIndex(model->swashRingData.type); + populateSourceCB(ui->swashCollectiveSource, model->swashRingData.collectiveSource, model, POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS); + ui->swashRingVal->setValue(model->swashRingData.value); + if (firmware->getCapability(VirtualInputs)) { + populateSourceCB(ui->swashElevatorSource, model->swashRingData.elevatorSource, model, POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS); + populateSourceCB(ui->swashAileronSource, model->swashRingData.aileronSource, model, POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS); + ui->swashElevatorWeight->setValue(model->swashRingData.elevatorWeight); + ui->swashAileronWeight->setValue(model->swashRingData.aileronWeight); + ui->swashCollectiveWeight->setValue(model->swashRingData.collectiveWeight); + } + else { + ui->swashElevatorInvert->setChecked(model->swashRingData.elevatorWeight < 0); + ui->swashAileronInvert->setChecked(model->swashRingData.aileronWeight < 0); + ui->swashCollectiveInvert->setChecked(model->swashRingData.collectiveWeight < 0); + } lock = false; } @@ -40,12 +69,21 @@ void HeliPanel::update() void HeliPanel::edited() { if (!lock) { - model->swashRingData.type = ui->swashTypeCB->currentIndex(); - model->swashRingData.collectiveSource = ui->swashCollectiveCB->itemData(ui->swashCollectiveCB->currentIndex()).toInt(); - model->swashRingData.value = ui->swashRingValSB->value(); - model->swashRingData.invertELE = ui->swashInvertELE->isChecked(); - model->swashRingData.invertAIL = ui->swashInvertAIL->isChecked(); - model->swashRingData.invertCOL = ui->swashInvertCOL->isChecked(); + model->swashRingData.type = ui->swashType->currentIndex(); + model->swashRingData.collectiveSource = ui->swashCollectiveSource->itemData(ui->swashCollectiveSource->currentIndex()).toInt(); + model->swashRingData.value = ui->swashRingVal->value(); + if (firmware->getCapability(VirtualInputs)) { + model->swashRingData.elevatorSource = ui->swashElevatorSource->itemData(ui->swashElevatorSource->currentIndex()).toInt(); + model->swashRingData.aileronSource = ui->swashAileronSource->itemData(ui->swashAileronSource->currentIndex()).toInt(); + model->swashRingData.elevatorWeight = ui->swashElevatorWeight->value(); + model->swashRingData.aileronWeight = ui->swashAileronWeight->value(); + model->swashRingData.collectiveWeight = ui->swashCollectiveWeight->value(); + } + else { + model->swashRingData.elevatorWeight = (ui->swashElevatorInvert->isChecked() ? -100 : 100); + model->swashRingData.aileronWeight = (ui->swashAileronInvert->isChecked() ? -100 : 100); + model->swashRingData.collectiveWeight = (ui->swashCollectiveInvert->isChecked() ? -100 : 100); + } emit modified(); } } diff --git a/companion/src/modeledit/heli.ui b/companion/src/modeledit/heli.ui index a248c9df7..bbe91d8fd 100644 --- a/companion/src/modeledit/heli.ui +++ b/companion/src/modeledit/heli.ui @@ -17,40 +17,15 @@ 6 - - - - - - Invert Elevator - - - - - - - Invert Aileron - - - - - - - Invert Collective - - - - - - + - Invert + Collective - + Off @@ -78,25 +53,69 @@ - - - - Collective + + + + 0 - + + + + + + + + + + -100 + + + 100 + + + 1 + + + 100 + + + + - - + + + + + + Invert Elevator + + + + + + + Invert Aileron + + + + + + + Invert Collective + + + + - - + + - Swash Type + Elevator - + @@ -114,14 +133,14 @@ - - + + - Swash Ring + Invert - + Qt::Vertical @@ -134,6 +153,85 @@ + + + + Swash Ring + + + + + + + Swash Type + + + + + + + 0 + + + + + + + + + + + -100 + + + 100 + + + 1 + + + 100 + + + + + + + + + Aileron + + + + + + + 0 + + + + + + + + + + + -100 + + + 100 + + + 1 + + + 100 + + + + + diff --git a/radio/src/gui/Taranis/menu_model_heli.cpp b/radio/src/gui/Taranis/menu_model_heli.cpp index e489569a1..8e5e5dfdf 100755 --- a/radio/src/gui/Taranis/menu_model_heli.cpp +++ b/radio/src/gui/Taranis/menu_model_heli.cpp @@ -37,17 +37,17 @@ enum menuModelHeliItems { ITEM_HELI_SWASHTYPE, - ITEM_HELI_ELESOURCE, - ITEM_HELI_AILSOURCE, - ITEM_HELI_COLSOURCE, ITEM_HELI_SWASHRING, - ITEM_HELI_ELEDIRECTION, - ITEM_HELI_AILDIRECTION, - ITEM_HELI_COLDIRECTION, + ITEM_HELI_ELE, + ITEM_HELI_ELE_WEIGHT, + ITEM_HELI_AIL, + ITEM_HELI_AIL_WEIGHT, + ITEM_HELI_COL, + ITEM_HELI_COL_WEIGHT, ITEM_HELI_MAX }; -#define HELI_PARAM_OFS (23*FW) +#define MODEL_HELI_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH) void menuModelHeli(uint8_t event) { @@ -56,51 +56,58 @@ void menuModelHeli(uint8_t event) int sub = m_posVert; for (unsigned int i=0; i0) ? BLINK|INVERS : INVERS); LcdFlags attr = (sub == k ? blink : 0); switch(k) { case ITEM_HELI_SWASHTYPE: - g_model.swashR.type = selectMenuItem(HELI_PARAM_OFS, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_MAX, attr, event); - break; - - case ITEM_HELI_ELESOURCE: - lcd_putsLeft(y, STR_ELEVATOR_SOURCE); - if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.elevatorSource, 0, MIXSRC_LAST_CH); - putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.elevatorSource, attr); - break; - - case ITEM_HELI_AILSOURCE: - lcd_putsLeft(y, STR_AILERON_SOURCE); - if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.aileronSource, 0, MIXSRC_LAST_CH); - putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.aileronSource, attr); - break; - - case ITEM_HELI_COLSOURCE: - lcd_putsLeft(y, STR_COLLECTIVE_SOURCE); - if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH); - putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.collectiveSource, attr); + g_model.swashR.type = selectMenuItem(MODEL_HELI_2ND_COLUMN, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_MAX, attr, event); break; case ITEM_HELI_SWASHRING: lcd_putsLeft(y, STR_SWASHRING); - lcd_outdezAtt(HELI_PARAM_OFS, y, g_model.swashR.value, LEFT|attr); + lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.value, LEFT|attr); if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.swashR.value, 100); break; - case ITEM_HELI_ELEDIRECTION: - g_model.swashR.invertELE = selectMenuItem(HELI_PARAM_OFS, y, STR_ELEDIRECTION, STR_MMMINV, g_model.swashR.invertELE, 0, 1, attr, event); + case ITEM_HELI_ELE: + lcd_putsLeft(y, "Elevator" /*STR_ELEVATOR_SOURCE*/); + putsMixerSource(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.elevatorSource, attr); + if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.elevatorSource, 0, MIXSRC_LAST_CH); break; - case ITEM_HELI_AILDIRECTION: - g_model.swashR.invertAIL = selectMenuItem(HELI_PARAM_OFS, y, STR_AILDIRECTION, STR_MMMINV, g_model.swashR.invertAIL, 0, 1, attr, event); + case ITEM_HELI_ELE_WEIGHT: + lcd_puts(INDENT_WIDTH, y, STR_WEIGHT); + lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.elevatorWeight, LEFT|attr); + if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.elevatorWeight, -100, 100); break; - case ITEM_HELI_COLDIRECTION: - g_model.swashR.invertCOL = selectMenuItem(HELI_PARAM_OFS, y, STR_COLDIRECTION, STR_MMMINV, g_model.swashR.invertCOL, 0, 1, attr, event); + case ITEM_HELI_AIL: + lcd_putsLeft(y, "Aileron" /*STR_ELEVATOR_SOURCE*/); + putsMixerSource(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.aileronSource, attr); + if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.aileronSource, 0, MIXSRC_LAST_CH); break; + + case ITEM_HELI_AIL_WEIGHT: + lcd_puts(INDENT_WIDTH, y, STR_WEIGHT); + lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.aileronWeight, LEFT|attr); + if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.aileronWeight, -100, 100); + break; + + case ITEM_HELI_COL: + lcd_putsLeft(y, "Collective" /*STR_ELEVATOR_SOURCE*/); + putsMixerSource(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.collectiveSource, attr); + if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH); + break; + + case ITEM_HELI_COL_WEIGHT: + lcd_puts(INDENT_WIDTH, y, STR_WEIGHT); + lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.collectiveWeight, LEFT|attr); + if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.collectiveWeight, -100, 100); + break; + } } } diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 039e71948..da0f26b73 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -37,7 +37,7 @@ #include "opentx.h" #include "timers.h" -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) int8_t virtualInputsTrims[NUM_INPUTS]; #else int16_t rawAnas[NUM_INPUTS] = {0}; @@ -67,7 +67,7 @@ int16_t ex_chans[NUM_CHNOUT] = {0}; // Outputs (before LIMITS) of the last perMa void applyExpos(int16_t *anas, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS) { -#if !defined(PCBTARANIS) +#if !defined(VIRTUALINPUTS) int16_t anas2[NUM_INPUTS]; // values before expo, to ensure same expo base when multiple expo lines are used memcpy(anas2, anas, sizeof(anas2)); #endif @@ -85,7 +85,7 @@ void applyExpos(int16_t *anas, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS) if (ed->flightModes & (1<swtch)) { -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) int v; if (ed->srcRaw == ovwrIdx) { v = ovwrValue; @@ -107,7 +107,7 @@ void applyExpos(int16_t *anas, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS) cur_chn = ed->chn; //========== CURVE================= -#if defined(PCBTARANIS) +#if defined(XCURVES) if (ed->curve.value) { v = applyCurve(v, ed->curve); } @@ -126,7 +126,7 @@ void applyExpos(int16_t *anas, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS) weight = calc100to256(weight); v = ((int32_t)v * weight) >> 8; -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) //========== OFFSET =============== int16_t offset = GET_GVAR(ed->offset, -100, 100, mixerCurrentFlightMode); if (offset) v += calc100toRESX(offset); @@ -243,13 +243,13 @@ getvalue_t getValue(mixsrc_t i) { if (i==MIXSRC_NONE) return 0; -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) else if (i <= MIXSRC_LAST_INPUT) { return anas[i-MIXSRC_FIRST_INPUT]; } #endif -#if defined(PCBTARANIS) +#if defined(LUAINPUTS) else if (i 1024 if (g_model.swashR.type) { -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) getvalue_t vp = heliEleValue + getSourceTrimValue(g_model.swashR.elevatorSource); getvalue_t vr = heliAilValue + getSourceTrimValue(g_model.swashR.aileronSource); #else @@ -624,9 +631,15 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) if (g_model.swashR.collectiveSource) vc = getValue(g_model.swashR.collectiveSource); +#if defined(VIRTUALINPUTS) + vp = (vp * g_model.swashR.elevatorWeight) / 100; + vr = (vr * g_model.swashR.aileronWeight) / 100; + vc = (vc * g_model.swashR.collectiveWeight) / 100; +#else if (g_model.swashR.invertELE) vp = -vp; if (g_model.swashR.invertAIL) vr = -vr; if (g_model.swashR.invertCOL) vc = -vc; +#endif switch (g_model.swashR.type) { case SWASH_TYPE_120: @@ -705,7 +718,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) MIXER_LINE_DISABLE(); } -#if defined(PCBTARANIS) && defined(LUA_MODEL_SCRIPTS) +#if defined(LUA_MODEL_SCRIPTS) // disable mixer if Lua script is used as source and script was killed if (mixEnabled && md->srcRaw >= MIXSRC_FIRST_LUA && md->srcRaw <= MIXSRC_LAST_LUA) { div_t qr = div(md->srcRaw-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); @@ -718,7 +731,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) //========== VALUE =============== getvalue_t v = 0; if (mode > e_perout_mode_inactive_flight_mode) { -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) if (!mixEnabled) { continue; } @@ -735,7 +748,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) #endif } else { -#if !defined(PCBTARANIS) +#if !defined(VIRTUALINPUTS) if (stickIndex < NUM_STICKS) { v = md->noExpo ? rawAnas[stickIndex] : anas[stickIndex]; } @@ -804,7 +817,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) //========== TRIMS ================ if (!(mode & e_perout_mode_notrims)) { -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) if (md->carryTrim == 0) { v += getSourceTrimValue(md->srcRaw); } @@ -873,7 +886,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) } //========== CURVES =============== -#if defined(PCBTARANIS) +#if defined(XCURVES) if (apply_offset_and_curve && md->curve.value) { v = applyCurve(v, md->curve); } @@ -893,7 +906,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) } //========== DIFFERENTIAL ========= -#if !defined(PCBTARANIS) +#if !defined(XCURVES) if (md->curveMode == MODE_DIFFERENTIAL) { // @@@2 also recalculate curveParam to a 256 basis which ease the calculation later a lot int16_t curveParam = calc100to256(GET_GVAR(md->curveParam, -100, 100, mixerCurrentFlightMode)); diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 669ee3144..55811e292 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -1502,16 +1502,16 @@ enum SwashType { SWASH_TYPE_MAX = SWASH_TYPE_90 }; -#if defined(PCBTARANIS) +#if defined(VIRTUALINPUTS) PACK(typedef struct { - uint8_t invertELE:1; - uint8_t invertAIL:1; - uint8_t invertCOL:1; - uint8_t type:5; + uint8_t type; + uint8_t value; uint8_t collectiveSource; uint8_t aileronSource; uint8_t elevatorSource; - uint8_t value; + int8_t collectiveWeight; + int8_t aileronWeight; + int8_t elevatorWeight; }) SwashRingData; #else PACK(typedef struct {