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 {