feat(radio): allow prec. for mix slow up/dn to be set to 10 or 100ms (#4612)

This commit is contained in:
philmoz
2024-02-12 12:01:54 +10:00
committed by GitHub
parent 001854fbd6
commit 84c2d8577e
47 changed files with 491 additions and 292 deletions
@@ -134,6 +134,7 @@ Node convert<MixData>::encode(const MixData& rhs)
node["curve"] = rhs.curve;
node["delayUp"] = rhs.delayUp;
node["delayDown"] = rhs.delayDown;
node["speedPrec"] = rhs.speedPrec;
node["speedUp"] = rhs.speedUp;
node["speedDown"] = rhs.speedDown;
node["carryTrim"] = rhs.carryTrim;
@@ -156,6 +157,7 @@ bool convert<MixData>::decode(const Node& node, MixData& rhs)
node["curve"] >> rhs.curve;
node["delayUp"] >> rhs.delayUp;
node["delayDown"] >> rhs.delayDown;
node["speedPrec"] >> rhs.speedPrec;
node["speedUp"] >> rhs.speedUp;
node["speedDown"] >> rhs.speedDown;
node["carryTrim"] >> rhs.carryTrim;
+1
View File
@@ -49,6 +49,7 @@ class MixData {
CurveReference curve;
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedPrec;
unsigned int speedUp;
unsigned int speedDown;
int carryTrim;
+33 -8
View File
@@ -133,16 +133,11 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue()));
ui->warningCB->setCurrentIndex(md->mixWarn);
ui->mltpxCB->setCurrentIndex(md->mltpx);
ui->speedPrecCB->setCurrentIndex(md->speedPrec);
int scale=firmware->getCapability(SlowScale);
float range=firmware->getCapability(SlowRange);
ui->slowDownSB->setMaximum(range / scale);
ui->slowDownSB->setSingleStep(1.0 / scale);
ui->slowDownSB->setDecimals((scale == 1 ? 0 : 1));
ui->slowDownSB->setValue((float)md->speedDown/scale);
ui->slowUpSB->setMaximum(range / scale);
ui->slowUpSB->setSingleStep(1.0 / scale);
ui->slowUpSB->setDecimals((scale == 1 ? 0 : 1));
ui->slowUpSB->setValue((float)md->speedUp/scale);
ui->delayDownSB->setMaximum(range / scale);
ui->delayDownSB->setSingleStep(1.0 / scale);
ui->delayDownSB->setDecimals((scale == 1 ? 0 : 1));
@@ -152,6 +147,16 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
ui->delayUpSB->setDecimals((scale == 1 ? 0 : 1));
ui->delayUpSB->setValue((float)md->delayUp / scale);
if (md->speedPrec) scale = scale * 10;
ui->slowDownSB->setMaximum(range / scale);
ui->slowDownSB->setSingleStep(1.0 / scale);
ui->slowDownSB->setDecimals((scale == 1 ? 0 : scale == 10 ? 1 : 2));
ui->slowDownSB->setValue((float)md->speedDown/scale);
ui->slowUpSB->setMaximum(range / scale);
ui->slowUpSB->setSingleStep(1.0 / scale);
ui->slowUpSB->setDecimals((scale == 1 ? 0 : scale == 10 ? 1 : 2));
ui->slowUpSB->setValue((float)md->speedUp/scale);
valuesChanged();
connect(ui->mixerName,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
@@ -163,6 +168,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
connect(ui->mltpxCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged()));
connect(ui->delayDownSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
connect(ui->delayUpSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
connect(ui->speedPrecCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged()));
connect(ui->slowDownSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
connect(ui->slowUpSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
@@ -209,11 +215,30 @@ void MixerDialog::valuesChanged()
md->swtch = RawSwitch(ui->switchesCB->itemData(ui->switchesCB->currentIndex()).toInt());
md->mixWarn = ui->warningCB->currentIndex();
md->mltpx = (MltpxValue)ui->mltpxCB->currentIndex();
int scale = firmware->getCapability(SlowScale);
md->delayDown = round(ui->delayDownSB->value() * scale);
md->delayUp = round(ui->delayUpSB->value() * scale);
// Update values based on old precision (in case it changed)
if (md->speedPrec) scale = scale * 10;
md->speedDown = round(ui->slowDownSB->value() * scale);
md->speedUp = round(ui->slowUpSB->value() * scale);
// Get new precion and update controls
md->speedPrec = ui->speedPrecCB->currentIndex();
float range = firmware->getCapability(SlowRange);
scale = firmware->getCapability(SlowScale);
if (md->speedPrec) scale = scale * 10;
ui->slowDownSB->setMaximum(range / scale);
ui->slowDownSB->setSingleStep(1.0 / scale);
ui->slowDownSB->setDecimals((scale == 1 ? 0 : scale == 10 ? 1 : 2));
ui->slowDownSB->setValue((float)md->speedDown / scale);
ui->slowUpSB->setMaximum(range / scale);
ui->slowUpSB->setSingleStep(1.0 / scale);
ui->slowUpSB->setDecimals((scale == 1 ? 0 : scale == 10 ? 1 : 2));
ui->slowUpSB->setValue((float)md->speedUp / scale);
strcpy(md->name, ui->mixerName->text().toLatin1());
md->flightModes = 0;
+261 -240
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>571</height>
<width>556</width>
<height>623</height>
</rect>
</property>
<property name="sizePolicy">
@@ -29,24 +29,226 @@
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,0">
<item row="5" column="0">
<widget class="QLabel" name="trimLabel">
<property name="text">
<string>Include Trim</string>
<item row="8" column="1" colspan="2">
<widget class="QComboBox" name="switchesCB">
<property name="whatsThis">
<string>Switch used by the mix.
If blank then the mix is considered to be &quot;ON&quot; all the time.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Offset</string>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="sourceCB">
<property name="whatsThis">
<string>The source for the mixer</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<item row="4" column="0">
<widget class="QLabel" name="label_curve">
<property name="text">
<string>Weight</string>
<string>Curve</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,1">
<item>
<widget class="QCheckBox" name="weightGV">
<property name="text">
<string>GV</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="weightCB">
<property name="whatsThis">
<string>The source for the mixer</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="weightSB"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="10" column="1" colspan="2">
<widget class="QComboBox" name="mltpxCB">
<property name="whatsThis">
<string>Multiplexer
This determines how mixer values are added.
&quot;+&quot; means the value of the current mix is added to the previous mixes in the same channel.
&quot;*&quot; means the value of the current mix is amultiplied with the previous mixes in the same channel.
&quot;R&quot; means the value replaces the previous values. If the switch is off the value will be ignored.</string>
</property>
<item>
<property name="text">
<string>ADD</string>
</property>
</item>
<item>
<property name="text">
<string>MULTIPLY</string>
</property>
</item>
<item>
<property name="text">
<string>REPLACE</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,1">
<item>
<widget class="QCheckBox" name="offsetGV">
<property name="text">
<string>GV</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="offsetCB">
<property name="whatsThis">
<string>The source for the mixer</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="offsetSB"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="trimCB">
<item>
<property name="text">
<string>No</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
</widget>
</item>
<item row="9" column="1" colspan="2">
<widget class="QComboBox" name="warningCB">
<property name="whatsThis">
<string>Mixer warning.
Setting this value will cause a beep to be emmitted when this value is active.</string>
</property>
<item>
<property name="text">
<string>OFF</string>
</property>
</item>
<item>
<property name="text">
<string>1 Beep</string>
</property>
</item>
<item>
<property name="text">
<string>2 Beep</string>
</property>
</item>
<item>
<property name="text">
<string>3 Beep</string>
</property>
</item>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="MixDR_CB">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Switch</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_phases">
<property name="text">
<string>Flight modes</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_MixDR">
<property name="text">
<string>Include DR/Expo</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Warning</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="curveTypeCB">
<property name="whatsThis">
<string>The curve used by the mix</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Multiplex</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Source</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_name">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
@@ -207,226 +409,24 @@
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_name">
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Name</string>
<string>Weight</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Source</string>
<string>Offset</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_9">
<item row="5" column="0">
<widget class="QLabel" name="trimLabel">
<property name="text">
<string>Multiplex</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Warning</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="curveTypeCB">
<property name="whatsThis">
<string>The curve used by the mix</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_MixDR">
<property name="text">
<string>Include DR/Expo</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_phases">
<property name="text">
<string>Flight modes</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Switch</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="MixDR_CB">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="1" colspan="2">
<widget class="QComboBox" name="warningCB">
<property name="whatsThis">
<string>Mixer warning.
Setting this value will cause a beep to be emmitted when this value is active.</string>
</property>
<item>
<property name="text">
<string>OFF</string>
</property>
</item>
<item>
<property name="text">
<string>1 Beep</string>
</property>
</item>
<item>
<property name="text">
<string>2 Beep</string>
</property>
</item>
<item>
<property name="text">
<string>3 Beep</string>
</property>
</item>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="trimCB">
<item>
<property name="text">
<string>No</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,1">
<item>
<widget class="QCheckBox" name="offsetGV">
<property name="text">
<string>GV</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="offsetCB">
<property name="whatsThis">
<string>The source for the mixer</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="offsetSB"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="10" column="1" colspan="2">
<widget class="QComboBox" name="mltpxCB">
<property name="whatsThis">
<string>Multiplexer
This determines how mixer values are added.
&quot;+&quot; means the value of the current mix is added to the previous mixes in the same channel.
&quot;*&quot; means the value of the current mix is amultiplied with the previous mixes in the same channel.
&quot;R&quot; means the value replaces the previous values. If the switch is off the value will be ignored.</string>
</property>
<item>
<property name="text">
<string>ADD</string>
</property>
</item>
<item>
<property name="text">
<string>MULTIPLY</string>
</property>
</item>
<item>
<property name="text">
<string>REPLACE</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="sourceCB">
<property name="whatsThis">
<string>The source for the mixer</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_curve">
<property name="text">
<string>Curve</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,1">
<item>
<widget class="QCheckBox" name="weightGV">
<property name="text">
<string>GV</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="weightCB">
<property name="whatsThis">
<string>The source for the mixer</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="weightSB"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="8" column="1" colspan="2">
<widget class="QComboBox" name="switchesCB">
<property name="whatsThis">
<string>Switch used by the mix.
If blank then the mix is considered to be &quot;ON&quot; all the time.</string>
<string>Include Trim</string>
</property>
</widget>
</item>
@@ -477,8 +477,45 @@ If blank then the mix is considered to be &quot;ON&quot; all the time.</string>
</item>
</layout>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Slow up/dn prec</string>
</property>
</widget>
</item>
<item row="11" column="1" colspan="2">
<widget class="QComboBox" name="speedPrecCB">
<item>
<property name="text">
<string>0.0</string>
</property>
</item>
<item>
<property name="text">
<string>0.00</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0">
<item row="0" column="1">
@@ -621,22 +658,6 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
+4
View File
@@ -442,6 +442,10 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
scale = 1;
if (mix.delayDown || mix.delayUp)
str += " " + tr("Delay(u%1:d%2)").arg((double)mix.delayUp / scale).arg((double)mix.delayDown / scale).toHtmlEscaped();
if (mix.speedPrec) {
scale = scale * 10;
str += " " + tr("Slow precision(0.00)").toHtmlEscaped();
}
if (mix.speedDown || mix.speedUp)
str += " " + tr("Slow(u%1:d%2)").arg((double)mix.speedUp / scale).arg((double)mix.speedDown / scale).toHtmlEscaped();
if (mix.mixWarn)
+1 -1
View File
@@ -78,7 +78,7 @@ PACK(struct MixData {
uint16_t carryTrim:1;
uint16_t mixWarn:2; // mixer warning
uint16_t mltpx:2 ENUM(MixerMultiplex);
uint16_t spare:1 SKIP;
uint16_t speedPrec:1;
int32_t offset:13 CUST(in_read_weight,in_write_weight);
int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc);
uint32_t flightModes:9 CUST(r_flightModes, w_flightModes);
+2 -2
View File
@@ -113,9 +113,9 @@ void editSingleName(coord_t x, coord_t y, const char *label, char *name,
uint8_t size, event_t event, uint8_t active,
uint8_t old_editMode);
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay);
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay, uint8_t prec);
#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(y, event, attr, str, delay)
#define EDIT_DELAY(x, y, event, attr, str, delay, prec) editDelay(y, event, attr, str, delay, prec)
#define COPY_MODE 1
#define MOVE_MODE 2
+2 -2
View File
@@ -21,10 +21,10 @@
#include "opentx.h"
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay)
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay, uint8_t prec)
{
lcdDrawTextAlignedLeft(y, str);
lcdDrawNumber(MIXES_2ND_COLUMN, y, delay, attr|PREC1|LEFT);
lcdDrawNumber(MIXES_2ND_COLUMN, y, delay, attr|prec|LEFT);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX);
return delay;
}
+2 -2
View File
@@ -155,11 +155,11 @@ void menuModelFlightModeOne(event_t event)
break;
#endif
case ITEM_MODEL_FLIGHT_MODE_FADE_IN:
fm->fadeIn = EDIT_DELAY(0, y, event, attr, STR_FADEIN, fm->fadeIn);
fm->fadeIn = EDIT_DELAY(0, y, event, attr, STR_FADEIN, fm->fadeIn, PREC1);
break;
case ITEM_MODEL_FLIGHT_MODE_FADE_OUT:
fm->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, fm->fadeOut);
fm->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, fm->fadeOut, PREC1);
break;
#if defined(GVARS)
+9 -4
View File
@@ -35,6 +35,7 @@ enum MixFields {
MIX_FIELD_MLTPX,
MIX_FIELD_DELAY_UP,
MIX_FIELD_DELAY_DOWN,
MIX_FIELD_SLOW_PREC,
MIX_FIELD_SLOW_UP,
MIX_FIELD_SLOW_DOWN,
MIX_FIELD_COUNT
@@ -194,19 +195,23 @@ void menuModelMixOne(event_t event)
break;
case MIX_FIELD_DELAY_UP:
md2->delayUp = EDIT_DELAY(0, y, event, attr, STR_DELAYUP, md2->delayUp);
md2->delayUp = EDIT_DELAY(0, y, event, attr, STR_DELAYUP, md2->delayUp, PREC1);
break;
case MIX_FIELD_DELAY_DOWN:
md2->delayDown = EDIT_DELAY(0, y, event, attr, STR_DELAYDOWN, md2->delayDown);
md2->delayDown = EDIT_DELAY(0, y, event, attr, STR_DELAYDOWN, md2->delayDown, PREC1);
break;
case MIX_FIELD_SLOW_PREC:
md2->speedPrec = editChoice(MIXES_2ND_COLUMN, y, STR_MIX_SLOW_PREC, &STR_VPREC[1], md2->speedPrec, 0, 1, attr, event);
break;
case MIX_FIELD_SLOW_UP:
md2->speedUp = EDIT_DELAY(0, y, event, attr, STR_SLOWUP, md2->speedUp);
md2->speedUp = EDIT_DELAY(0, y, event, attr, STR_SLOWUP, md2->speedUp, (md2->speedPrec ? PREC2 : PREC1));
break;
case MIX_FIELD_SLOW_DOWN:
md2->speedDown = EDIT_DELAY(0, y, event, attr, STR_SLOWDOWN, md2->speedDown);
md2->speedDown = EDIT_DELAY(0, y, event, attr, STR_SLOWDOWN, md2->speedDown, (md2->speedPrec ? PREC2 : PREC1));
break;
}
y += FH;
+2 -2
View File
@@ -132,9 +132,9 @@ void editSingleName(coord_t x, coord_t y, const char *label, char *name,
uint8_t size, event_t event, uint8_t active,
uint8_t old_editMode);
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay);
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay, uint8_t prec);
#define EDIT_DELAY(y, event, attr, str, delay) editDelay(y, event, attr, str, delay)
#define EDIT_DELAY(y, event, attr, str, delay, prec) editDelay(y, event, attr, str, delay, prec)
void copySelection(char * dst, const char * src, uint8_t size);
+2 -2
View File
@@ -46,10 +46,10 @@ const MenuHandler menuTabModel[] = {
{ menuModelDisplay, nullptr }
};
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay)
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay, uint8_t prec)
{
lcdDrawTextAlignedLeft(y, str);
lcdDrawNumber(MIXES_2ND_COLUMN, y, delay, attr|PREC1|LEFT);
lcdDrawNumber(MIXES_2ND_COLUMN, y, delay, attr|prec|LEFT);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX);
return delay;
}
+9 -4
View File
@@ -35,6 +35,7 @@ enum MixFields {
MIX_FIELD_MLTPX,
MIX_FIELD_DELAY_UP,
MIX_FIELD_DELAY_DOWN,
MIX_FIELD_SLOW_PREC,
MIX_FIELD_SLOW_UP,
MIX_FIELD_SLOW_DOWN,
MIX_FIELD_COUNT
@@ -184,19 +185,23 @@ void menuModelMixOne(event_t event)
break;
case MIX_FIELD_DELAY_UP:
md2->delayUp = EDIT_DELAY(y, event, attr, STR_DELAYUP, md2->delayUp);
md2->delayUp = EDIT_DELAY(y, event, attr, STR_DELAYUP, md2->delayUp, PREC1);
break;
case MIX_FIELD_DELAY_DOWN:
md2->delayDown = EDIT_DELAY(y, event, attr, STR_DELAYDOWN, md2->delayDown);
md2->delayDown = EDIT_DELAY(y, event, attr, STR_DELAYDOWN, md2->delayDown, PREC1);
break;
case MIX_FIELD_SLOW_PREC:
md2->speedPrec = editChoice(MIXES_2ND_COLUMN, y, STR_MIX_SLOW_PREC, &STR_VPREC[1], md2->speedPrec, 0, 1, attr, event);
break;
case MIX_FIELD_SLOW_UP:
md2->speedUp = EDIT_DELAY(y, event, attr, STR_SLOWUP, md2->speedUp);
md2->speedUp = EDIT_DELAY(y, event, attr, STR_SLOWUP, md2->speedUp, (md2->speedPrec ? PREC2 : PREC1));
break;
case MIX_FIELD_SLOW_DOWN:
md2->speedDown = EDIT_DELAY(y, event, attr, STR_SLOWDOWN, md2->speedDown);
md2->speedDown = EDIT_DELAY(y, event, attr, STR_SLOWDOWN, md2->speedDown, (md2->speedPrec ? PREC2 : PREC1));
break;
}
y += FH;
+26 -6
View File
@@ -98,16 +98,36 @@ void MixEditAdvanced::buildBody(FormWindow* form)
SET_VALUE(mix->delayDown, newValue), 0, PREC1);
edit->setSuffix("s");
// Slow up/down precision
#if LCD_W > LCD_H
grid.setColSpan(2);
#endif
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_MIX_SLOW_PREC, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, &STR_VPREC[1], 0, 1,
GET_DEFAULT(mix->speedPrec),
[=](int newValue) {
mix->speedPrec = newValue;
slowUp->setTextFlags(mix->speedPrec ? PREC2 : PREC1);
slowUp->update();
slowDn->setTextFlags(mix->speedPrec ? PREC2 : PREC1);
slowDn->update();
SET_DIRTY();
});
#if LCD_W > LCD_H
grid.setColSpan(1);
#endif
// Slow up
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_SLOWUP, 0, COLOR_THEME_PRIMARY1);
edit = new NumberEdit(line, rect_t{0, 0, 100, 0}, 0, DELAY_MAX, GET_DEFAULT(mix->speedUp),
SET_VALUE(mix->speedUp, newValue), 0, PREC1);
edit->setSuffix("s");
slowUp = new NumberEdit(line, rect_t{0, 0, 100, 0}, 0, DELAY_MAX, GET_DEFAULT(mix->speedUp),
SET_VALUE(mix->speedUp, newValue), 0, mix->speedPrec ? PREC2 : PREC1);
slowUp->setSuffix("s");
// Slow down
new StaticText(line, rect_t{}, STR_SLOWDOWN, 0, COLOR_THEME_PRIMARY1);
edit = new NumberEdit(line, rect_t{0, 0, 100, 0}, 0, DELAY_MAX, GET_DEFAULT(mix->speedDown),
SET_VALUE(mix->speedDown, newValue), 0, PREC1);
edit->setSuffix("s");
slowDn = new NumberEdit(line, rect_t{0, 0, 100, 0}, 0, DELAY_MAX, GET_DEFAULT(mix->speedDown),
SET_VALUE(mix->speedDown, newValue), 0, mix->speedPrec ? PREC2 : PREC1);
slowDn->setSuffix("s");
}
+3
View File
@@ -26,6 +26,7 @@
#include "curve.h"
class FormWindow;
class NumberEdit;
class MixEditAdvanced : public Page
{
@@ -35,6 +36,8 @@ class MixEditAdvanced : public Page
protected:
uint8_t channel;
uint8_t index;
NumberEdit* slowUp;
NumberEdit* slowDn;
void buildHeader(Window *window);
void buildBody(FormWindow *window);
+3 -2
View File
@@ -930,17 +930,18 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
// rate equals a full range for one second; if less time is passed rate is accordingly smaller
// if one second passed, rate would be 2048 (full motion)*256(recalculated weight)*100(100 ticks needed for one second)
int32_t currentValue = ((int32_t) v<<DEL_MULT_SHIFT);
int32_t precMult = md->speedPrec ? 1 : 10;
if (diff > 0) {
if (s_mixer_first_run_done && md->speedUp > 0) {
// if a speed upwards is defined recalculate the new value according configured speed; the higher the speed the smaller the add value is
int32_t newValue = tact+rate/((int16_t)10*md->speedUp);
int32_t newValue = tact+rate/((int16_t)precMult*md->speedUp);
if (newValue<currentValue) currentValue = newValue; // Endposition; prevent toggling around the destination
}
}
else { // if is <0 because ==0 is not possible
if (s_mixer_first_run_done && md->speedDown > 0) {
// see explanation in speedUp
int32_t newValue = tact-rate/((int16_t)10*md->speedDown);
int32_t newValue = tact-rate/((int16_t)precMult*md->speedDown);
if (newValue>currentValue) currentValue = newValue; // Endposition; prevent toggling around the destination
}
}
@@ -397,7 +397,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -424,7 +424,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -424,7 +424,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -397,7 +397,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -397,7 +397,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -426,7 +426,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -426,7 +426,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -397,7 +397,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -398,7 +398,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
@@ -400,7 +400,7 @@ static const struct YamlNode struct_MixData[] = {
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "speedPrec", 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
+79 -7
View File
@@ -31,11 +31,11 @@ class MixerTest : public OpenTxTest {};
GTEST_ASSERT_EQ((value), chans[(channel)]); \
}
#define CHECK_SLOW_MOVEMENT(channel, sign, duration) \
#define CHECK_SLOW_MOVEMENT(channel, sign, duration, max_duration) \
do { \
for (int i=1; i<=(duration); i++) { \
evalFlightModeMixes(e_perout_mode_normal, 1); \
lastAct = lastAct + (sign) * (1<<19)/500; /* 100 on ARM */ \
lastAct = lastAct + (sign) * (1<<19)/max_duration; \
GTEST_ASSERT_EQ(256 * (lastAct >> 8), chans[(channel)]); \
} \
} while (0)
@@ -701,10 +701,10 @@ TEST_F(MixerTest, SlowOnPhase)
evalFlightModeMixes(e_perout_mode_normal, 0);
EXPECT_EQ(chans[0], 0);
CHECK_SLOW_MOVEMENT(0, +1, 250);
CHECK_SLOW_MOVEMENT(0, +1, 250, 500);
mixerCurrentFlightMode = 1;
CHECK_SLOW_MOVEMENT(0, -1, 250);
CHECK_SLOW_MOVEMENT(0, -1, 250, 500);
}
TEST_F(MixerTest, SlowOnSwitchSource)
@@ -721,11 +721,56 @@ TEST_F(MixerTest, SlowOnSwitchSource)
s_mixer_first_run_done = true;
simuSetSwitch(switchIndex, -1);
CHECK_SLOW_MOVEMENT(0, -1, 250);
CHECK_SLOW_MOVEMENT(0, -1, 250, 500);
EXPECT_EQ(chans[0], -CHANNEL_MAX);
simuSetSwitch(switchIndex, 1);
CHECK_SLOW_MOVEMENT(0, +1, 500);
CHECK_SLOW_MOVEMENT(0, +1, 500, 500);
}
TEST_F(MixerTest, SlowOnPhasePrec10ms)
{
g_model.flightModeData[1].swtch = SWSRC_FIRST_SWITCH;
g_model.mixData[0].destCh = 0;
g_model.mixData[0].mltpx = MLTPX_ADD;
g_model.mixData[0].srcRaw = MIXSRC_MAX;
g_model.mixData[0].weight = 100;
g_model.mixData[0].flightModes = 0x2 + 0x4 + 0x8 + 0x10 /*only enabled in phase 0*/;
g_model.mixData[0].speedUp = 50;
g_model.mixData[0].speedDown = 50;
g_model.mixData[0].speedPrec = 1;
s_mixer_first_run_done = true;
mixerCurrentFlightMode = 0;
evalFlightModeMixes(e_perout_mode_normal, 0);
EXPECT_EQ(chans[0], 0);
CHECK_SLOW_MOVEMENT(0, +1, 25, 50);
mixerCurrentFlightMode = 1;
CHECK_SLOW_MOVEMENT(0, -1, 25, 50);
}
TEST_F(MixerTest, SlowOnSwitchSourcePrec10ms)
{
g_model.mixData[0].destCh = 0;
g_model.mixData[0].mltpx = MLTPX_ADD;
g_eeGeneral.switchConfig = 0x03;
g_model.mixData[0].srcRaw = MIXSRC_FIRST_SWITCH;
int switchIndex = 0;
g_model.mixData[0].weight = 100;
g_model.mixData[0].speedUp = 50;
g_model.mixData[0].speedDown = 50;
g_model.mixData[0].speedPrec = 1;
s_mixer_first_run_done = true;
simuSetSwitch(switchIndex, -1);
CHECK_SLOW_MOVEMENT(0, -1, 25, 50);
EXPECT_EQ(chans[0], -CHANNEL_MAX);
simuSetSwitch(switchIndex, 1);
CHECK_SLOW_MOVEMENT(0, +1, 50, 50);
}
TEST_F(MixerTest, SlowDisabledOnStartup)
@@ -818,7 +863,34 @@ TEST_F(MixerTest, SlowOnMultiply)
s_mixer_first_run_done = true;
simuSetSwitch(0, 1);
CHECK_SLOW_MOVEMENT(0, 1, 250);
CHECK_SLOW_MOVEMENT(0, 1, 250, 500);
simuSetSwitch(0, -1);
CHECK_NO_MOVEMENT(0, CHANNEL_MAX, 250);
simuSetSwitch(0, 1);
CHECK_NO_MOVEMENT(0, CHANNEL_MAX, 250);
}
TEST_F(MixerTest, SlowOnMultiplyPrec10ms)
{
g_model.mixData[0].destCh = 0;
g_model.mixData[0].mltpx = MLTPX_ADD;
g_model.mixData[0].srcRaw = MIXSRC_MAX;
g_model.mixData[0].weight = 100;
g_model.mixData[1].destCh = 0;
g_model.mixData[1].mltpx = MLTPX_MUL;
g_model.mixData[1].srcRaw = MIXSRC_MAX;
g_model.mixData[1].weight = 100;
g_model.mixData[1].swtch = SWSRC_FIRST_SWITCH;
g_model.mixData[1].speedUp = 50;
g_model.mixData[1].speedDown = 50;
g_model.mixData[1].speedPrec = 1;
s_mixer_first_run_done = true;
simuSetSwitch(0, 1);
CHECK_SLOW_MOVEMENT(0, 1, 25, 50);
simuSetSwitch(0, -1);
CHECK_NO_MOVEMENT(0, CHANNEL_MAX, 250);
+2
View File
@@ -1097,3 +1097,5 @@ ISTR(SORT_ORDERS);
const char STR_SORT_MODELS_BY[] = TR_SORT_MODELS_BY;
const char STR_CREATE_NEW[] = TR_CREATE_NEW;
#endif
const char STR_MIX_SLOW_PREC[] = TR_MIX_SLOW_PREC;
+2
View File
@@ -1285,5 +1285,7 @@ extern const char STR_SORT_MODELS_BY[];
extern const char STR_CREATE_NEW[];
#endif
extern const char STR_MIX_SLOW_PREC[];
#endif // _TRANSLATIONS_H_
+2
View File
@@ -1271,3 +1271,5 @@
#define TR_SORT_ORDERS "名称 A-Z","名称 Z-A","不常用","常用"
#define TR_SORT_MODELS_BY "排序"
#define TR_CREATE_NEW "新建"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1291,3 +1291,5 @@
#define TR_SORT_ORDERS "Název A-Z","Název Z-A","Nejméne používané","Nejvíce používané"
#define TR_SORT_MODELS_BY "Seřadit modely podle"
#define TR_CREATE_NEW "Vytvořit"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1296,3 +1296,5 @@
#define TR_SORT_ORDERS "Navn A-Z","Navn Z-A","Sidst anvendt","Mest anvendt"
#define TR_SORT_MODELS_BY "Sorter modeller"
#define TR_CREATE_NEW "Opret"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1287,3 +1287,5 @@
#define TR_SORT_ORDERS "Name A-Z","Name Z-A","Wenig benutzt","Meist benutzt"
#define TR_SORT_MODELS_BY "Modelle sortieren nach"
#define TR_CREATE_NEW "Erstelle"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1284,3 +1284,5 @@
#define TR_SORT_ORDERS "Name A-Z","Name Z-A","Least used","Most used"
#define TR_SORT_MODELS_BY "Sort models by"
#define TR_CREATE_NEW "Create"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1284,3 +1284,5 @@
#define TR_SORT_ORDERS "Name A-Z","Name Z-A","Least used","Most used"
#define TR_SORT_MODELS_BY "Sort models by"
#define TR_CREATE_NEW "Create"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1300,3 +1300,5 @@
#define TR_SORT_ORDERS "Name A-Z","Name Z-A","Least used","Most used"
#define TR_SORT_MODELS_BY "Sort models by"
#define TR_CREATE_NEW "Create"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1301,3 +1301,5 @@
#define TR_SORT_ORDERS "Nom A-Z","Nom Z-A","Dernier utilisé","Couramment utilisé"
#define TR_SORT_MODELS_BY "Trier modèles par"
#define TR_CREATE_NEW "Créer"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1287,3 +1287,5 @@
#define TR_SORT_ORDERS "A-Z סידור","Z-A סידור","יותר בשימוש","פחות בשימוש"
#define TR_SORT_MODELS_BY "סדר תצוגה"
#define TR_CREATE_NEW "יצירה חדשה"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1279,3 +1279,5 @@
#define TR_SORT_ORDERS "Nome A-Z","Nome Z-A","Meno utilizzato","Più utilizzato"
#define TR_SORT_MODELS_BY "Ordina modelli per"
#define TR_CREATE_NEW "Crea"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1284,3 +1284,5 @@
#define TR_SORT_ORDERS "名称 A-Z順","名称 Z-A順","利用の少ない順","利用の多い順"
#define TR_SORT_MODELS_BY "モデルをソート"
#define TR_CREATE_NEW "作成"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1291,3 +1291,5 @@
#define TR_SORT_ORDERS "Name A-Z","Name Z-A","Least used","Most used"
#define TR_SORT_MODELS_BY "Sort models by"
#define TR_CREATE_NEW "Create"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1278,3 +1278,5 @@
#define TR_SORT_ORDERS "Nazwa A-Z","Nazwa Z-A","Najrzadziej użyty","Najczęściej użyty"
#define TR_SORT_MODELS_BY "Sortuj modele"
#define TR_CREATE_NEW "Utwórz"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1282,3 +1282,5 @@
#define TR_SORT_ORDERS "Nome A-Z","Nome Z-A","Menos usado","Mais usado"
#define TR_SORT_MODELS_BY "Ordenar modelos por"
#define TR_CREATE_NEW "Criar"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1281,3 +1281,5 @@
#define TR_SORT_ORDERS "Имя A-Z","Имя Z-A","Редко испол","Часто испол"
#define TR_SORT_MODELS_BY "Сортировка моделей"
#define TR_CREATE_NEW "Создать"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1318,3 +1318,5 @@
#define TR_SORT_ORDERS "Namn A-Z","Namn Z-A","Minst använda","Mest använda"
#define TR_SORT_MODELS_BY "Sortera modeller"
#define TR_CREATE_NEW "Skapa"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1276,3 +1276,5 @@
#define TR_SORT_ORDERS "名稱 A-Z","名稱 Z-A","不常用","常用"
#define TR_SORT_MODELS_BY "排序"
#define TR_CREATE_NEW "新建"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")
+2
View File
@@ -1255,3 +1255,5 @@
#define TR_SORT_ORDERS "Назва A-Z","Назва Z-A","Найменш використ.","Найбільш використ."
#define TR_SORT_MODELS_BY "Сортувати моделі за"
#define TR_CREATE_NEW "Створити"
#define TR_MIX_SLOW_PREC TR("Slow prec", "Slow up/dn prec")