1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-25 01:05:10 +03:00

Merge branch '2.3' into 3djc/2.3-synced

This commit is contained in:
3djc 2021-03-14 10:51:46 +01:00
commit e3082756c9
76 changed files with 2494 additions and 2015 deletions

View file

@ -16,6 +16,8 @@ addons:
- libmpc3
- libfox-1.6-dev
- libgtest-dev
- lib32stdc++6
- libclang-common-6.0-dev
- clang-6.0
- python3-pip

View file

@ -2146,3 +2146,42 @@ Philip Garcia
Helder Simoes
Thomas Blanchin
Jean-Luc Mesnier
Michael Bajer
David Homewood
Marc Sanders
Буров Александр
Rudy T'Jolleyn
Jay Watkins
Blaz Vodopivec
David De Salvo
Willem Verschoren
Dennis Kathrens
Alan Aucote
Richard Jerome Danstrom
David Garcia-Mendia
Mark Jones
John Zseleczky
Xiao Sun
Glenn Harvey
Albrecht Friebel
Gunter Klemke
Travis McCarthy
Franz Zier
Ian Contessa
Sean Sadler
Richard F Janczak
Mateusz Dziadosz
Thomas Merchant
M L Perkins
Stefano Boggia
Новоселов Юрий
James Rhodes
Peter Gaskill
Jacques Temey
Anthony Challis
Gerard Falaise
George McGinnis
Antoine Soulie
Tjeerd Jager
Bertold Van den Bergh
Stefanie Zerbe

View file

@ -46,6 +46,8 @@ QString AbstractItemModel::idToString(const int value)
return "CustomFuncResetParam";
case IMID_TeleSource:
return "TeleSource";
case IMID_RssiSource:
return "RssiSource";
case IMID_CurveRefType:
return "CurveRefType";
case IMID_CurveRefFunc:
@ -109,7 +111,6 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, firmware->getCapability(RotaryEncoders));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches));
@ -170,7 +171,6 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -firmware->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, -firmware->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_TRIM, -board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchPositions));
@ -181,7 +181,6 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett
addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, firmware->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_VIRTUAL, firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, firmware->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
@ -420,7 +419,7 @@ CustomFuncActionItemModel::CustomFuncActionItemModel(const GeneralSettings * con
void CustomFuncActionItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(CustomFunctionData(AssignFunc(value)).funcToString(modelData));
item->setText(CustomFunctionData::funcToString((AssignFunc)value, modelData));
item->setData(CustomFunctionData::isFuncAvailable(value), IMDR_Available);
}
@ -447,7 +446,7 @@ CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettin
setId(IMID_CustomFuncResetParam);
setUpdateMask(IMUE_TeleSensors);
for (int i = 0; i < CustomFunctionData::resetParamCount(modelData); i++) {
for (int i = 0; i < CustomFunctionData::resetParamCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
setDynamicItemData(modelItem, i);
@ -457,10 +456,8 @@ CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettin
void CustomFuncResetParamItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
CustomFunctionData cfd = CustomFunctionData(AssignFunc::FuncReset);
cfd.param = value;
item->setText(cfd.paramToString(modelData));
item->setData(CustomFunctionData::isResetParamAvailable(modelData, value), IMDR_Available);
item->setText(CustomFunctionData::resetToString(value, modelData));
item->setData(CustomFunctionData::isResetParamAvailable(value, modelData), IMDR_Available);
}
void CustomFuncResetParamItemModel::update(const int event)
@ -488,7 +485,7 @@ TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const
if (!modelData)
return;
setUpdateMask(IMUE_TeleSensors);
setUpdateMask(IMUE_TeleSensors | IMUE_Modules);
const int count = firmware->getCapability(Sensors);
for (int i = -count; i <= count; ++i) {
@ -519,6 +516,49 @@ void TelemetrySourceItemModel::update(const int event)
}
}
//
// RssiSourceItemModel
//
RssiSourceItemModel::RssiSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RssiSource);
if (!modelData)
return;
setUpdateMask(IMUE_TeleSensors | IMUE_Modules);
for (int i = 0; i <= firmware->getCapability(Sensors); ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void RssiSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(SensorData::rssiSensorToString(modelData, value));
item->setData(SensorData::isRssiSensorAvailable(modelData, value), IMDR_Available);
}
void RssiSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i) {
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
}
emit updateComplete();
}
}
//
// CurveRefTypeItemModel
//
@ -624,6 +664,9 @@ void CompoundItemModelFactory::addItemModel(const int id)
case AbstractItemModel::IMID_TeleSource:
registerItemModel(new TelemetrySourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_RssiSource:
registerItemModel(new RssiSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CurveRefType:
registerItemModel(new CurveRefTypeItemModel(generalSettings, modelData, firmware, board, boardType));
break;

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef COMPOUNDITEMMODELS_H
#define COMPOUNDITEMMODELS_H
#pragma once
#include "rawsource.h"
#include "rawswitch.h"
@ -44,6 +43,7 @@ class AbstractItemModel: public QStandardItemModel
IMID_CustomFuncAction,
IMID_CustomFuncResetParam,
IMID_TeleSource,
IMID_RssiSource,
IMID_CurveRefType,
IMID_CurveRefFunc,
IMID_ReservedCount,
@ -78,8 +78,9 @@ class AbstractItemModel: public QStandardItemModel
IMUE_Scripts = 1 << 7,
IMUE_TeleSensors = 1 << 8,
IMUE_Timers = 1 << 9,
IMUE_Modules = 1 << 10,
IMUE_All = IMUE_SystemRefresh | IMUE_Channels | IMUE_Curves | IMUE_FlightModes | IMUE_GVars | IMUE_Inputs |
IMUE_LogicalSwitches | IMUE_Scripts | IMUE_TeleSensors | IMUE_Timers
IMUE_LogicalSwitches | IMUE_Scripts | IMUE_TeleSensors | IMUE_Timers | IMUE_Modules
};
Q_ENUM(ItemModelUpdateEvent)
@ -305,6 +306,21 @@ class TelemetrySourceItemModel: public AbstractDynamicItemModel
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class RssiSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RssiSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RssiSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CurveRefTypeItemModel : public AbstractStaticItemModel
{
Q_OBJECT
@ -361,5 +377,3 @@ class CompoundItemModelFactory
private:
void setSourceId(AbstractItemModel * itemModel);
};
#endif // COMPOUNDITEMMODELS_H

View file

@ -2,16 +2,21 @@
set(firmwares_SRCS
adjustmentreference.cpp
boards.cpp
curvedata.cpp
curvereference.cpp
customfunctiondata.cpp
eeprominterface.cpp
generalsettings.cpp
gvardata.cpp
io_data.cpp
input_data.cpp
flightmodedata.cpp
heli_data.cpp
logicalswitchdata.cpp
mixdata.cpp
modeldata.cpp
moduledata.cpp
multiprotocols.cpp
output_data.cpp
radiodata.cpp
radiodataconversionstate.cpp
rawsource.cpp

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "curvedata.h"
#include "radiodata.h"
CurveData::CurveData()
{
clear();
}
void CurveData::clear(int count)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i = 0; i < count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "constants.h"
#include <QtCore>
class CurvePoint {
public:
int8_t x;
int8_t y;
};
#define CURVEDATA_NAME_LEN 6
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[CURVEDATA_NAME_LEN + 1];
void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
};

View file

@ -22,6 +22,17 @@
#include "eeprominterface.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
#include "compounditemmodels.h"
void CustomFunctionData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
}
}
void CustomFunctionData::clear()
{
@ -36,12 +47,19 @@ bool CustomFunctionData::isEmpty() const
return (swtch.type == SWITCH_TYPE_NONE);
}
QString CustomFunctionData::nameToString(int index, bool globalContext) const
// static
QString CustomFunctionData::nameToString(const int index, const bool globalContext)
{
return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index + 1, 0, true);
}
QString CustomFunctionData::funcToString(const ModelData * model) const
{
return funcToString(func, model);
}
// static
QString CustomFunctionData::funcToString(const AssignFunc func, const ModelData * model)
{
if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast)
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
@ -76,7 +94,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
else if (func == FuncPlayValue)
return tr("Play Value");
else if (func == FuncPlayScript)
return tr("Play Script");
return tr("Lua Script");
else if (func == FuncLogs)
return tr("SD Logs");
else if (func == FuncVolume)
@ -94,9 +112,9 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
else if (func == FuncSetFailsafe)
return tr("Set Failsafe");
else if (func == FuncRangeCheckInternalModule)
return tr("RangeCheck Int. Module");
return tr("Range Check Int. Module");
else if (func == FuncRangeCheckExternalModule)
return tr("RangeCheck Ext. Module");
return tr("Range Check Ext. Module");
else if (func == FuncBindInternalModule)
return tr("Bind Int. Module");
else if (func == FuncBindExternalModule)
@ -106,53 +124,6 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
}
}
void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox * b, unsigned int value = 0)
{
int val = 0;
Firmware * firmware = Firmware::getCurrentVariant();
for (int i = 0; i < CPN_MAX_TIMERS; i++, val++) {
if (i < firmware->getCapability(Timers)) {
RawSource item = RawSource(SOURCE_TYPE_SPECIAL, i + SOURCE_TYPE_SPECIAL_TIMER1_IDX);
b->addItem(item.toString(model), val);
}
}
b->addItem(tr("Flight"), val++);
b->addItem(tr("Telemetry"), val++);
int reCount = firmware->getCapability(RotaryEncoders);
if (reCount == 1) {
b->addItem(tr("Rotary Encoder"), val++);
}
else if (reCount == 2) {
b->addItem(tr("REa"), val++);
b->addItem(tr("REb"), val++);
}
if (model) {
for (int i = 0; i < firmware->getCapability(Sensors); ++i) {
if (model->sensorData[i].isAvailable()) {
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3 * i);
b->addItem(item.toString(model), val + i);
}
}
}
b->setCurrentIndex(b->findData(value));
}
void CustomFunctionData::populatePlaySoundParams(QStringList & qs)
{
qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ;
qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ;
}
void CustomFunctionData::populateHapticParams(QStringList & qs)
{
qs << "0" << "1" << "2" << "3";
}
QString CustomFunctionData::paramToString(const ModelData * model) const
{
QStringList qs;
@ -163,31 +134,16 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
return QString("%1").arg(param / 10.0) + tr("s");
}
else if (func == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs);
if (param >= 0 && param < (int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
return playSoundToString(param);
}
else if (func == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs);
if (param >= 0 && param < (int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
return harpicToString(param);
}
else if (func == FuncReset) {
QComboBox cb;
CustomFunctionData::populateResetParams(model, &cb);
int pos = cb.findData(param);
if (pos >= 0)
return cb.itemText(pos);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
return resetToString(param, model);
}
else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) {
RawSource item(param);
return item.toString(model);
return RawSource(param).toString(model);
}
else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
@ -200,16 +156,14 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
else if (func >= FuncAdjustGV1 && func < FuncCount) {
switch (adjustMode) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value ") + QString("%1").arg(param);
return gvarAdjustModeToString(adjustMode) + QString(" %1").arg(param);
case FUNC_ADJUST_GVAR_SOURCE:
case FUNC_ADJUST_GVAR_GVAR:
return RawSource(param).toString();
case FUNC_ADJUST_GVAR_INCDEC:
float val;
QString unit;
val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
unit = model->gvarData[func - FuncAdjustGV1].unitToString();
return QString("Increment: %1%2").arg(val).arg(unit);
const float val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
const QString unit = model->gvarData[func - FuncAdjustGV1].unitToString();
return gvarAdjustModeToString(adjustMode) + QString(": %1%2").arg(val).arg(unit);
}
}
return "";
@ -217,15 +171,20 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
QString CustomFunctionData::repeatToString() const
{
if (repeatParam == -1) {
return tr("played once, not during startup");
return repeatToString(repeatParam);
}
// static
QString CustomFunctionData::repeatToString(const int value)
{
if (value == -1) {
return tr("Played once, not during startup");
}
else if (repeatParam == 0) {
return "";
else if (value == 0) {
return tr("No repeat");
}
else {
unsigned int step = 1;
return tr("repeat(%1s)").arg(step * repeatParam);
return tr("Repeat %1s").arg(value);
}
}
@ -246,7 +205,7 @@ QString CustomFunctionData::enabledToString() const
}
// static
bool CustomFunctionData::isFuncAvailable(int index)
bool CustomFunctionData::isFuncAvailable(const int index)
{
Firmware * fw = getCurrentFirmware();
@ -265,7 +224,7 @@ bool CustomFunctionData::isFuncAvailable(int index)
}
// static
int CustomFunctionData::funcContext(int index)
int CustomFunctionData::funcContext(const int index)
{
int ret = AllFunctionContexts;
@ -276,16 +235,42 @@ int CustomFunctionData::funcContext(int index)
return ret;
}
// static
int CustomFunctionData::resetParamCount(const ModelData * model)
QString CustomFunctionData::resetToString(const int value, const ModelData * model)
{
QComboBox cb;
CustomFunctionData::populateResetParams(model, &cb);
return cb.count();
Firmware * firmware = getCurrentFirmware();
int step = CPN_MAX_TIMERS;
if (value < step) {
if (value < firmware->getCapability(Timers))
return RawSource(SOURCE_TYPE_SPECIAL, value + SOURCE_TYPE_SPECIAL_TIMER1_IDX).toString(model);
else
return QString(CPN_STR_UNKNOWN_ITEM);
}
if (value < ++step)
return tr("Flight");
if (value < ++step)
return tr("Telemetry");
if (value < step + firmware->getCapability(Sensors))
return RawSource(SOURCE_TYPE_TELEMETRY, 3 * (value - step)).toString(model);
return QString(CPN_STR_UNKNOWN_ITEM);
}
// static
bool CustomFunctionData::isResetParamAvailable(const ModelData * model, int index)
int CustomFunctionData::resetParamCount()
{
Firmware * firmware = getCurrentFirmware();
return CPN_MAX_TIMERS + 2 + firmware->getCapability(Sensors);
}
// static
bool CustomFunctionData::isResetParamAvailable(const int index, const ModelData * model)
{
Firmware * firmware = getCurrentFirmware();
@ -295,20 +280,121 @@ bool CustomFunctionData::isResetParamAvailable(const ModelData * model, int inde
else
return false;
}
else if (index < CPN_MAX_TIMERS + firmware->getCapability(RotaryEncoders))
else if (index < CPN_MAX_TIMERS + 2)
return true;
else if (model && index < CPN_MAX_TIMERS + firmware->getCapability(RotaryEncoders) + firmware->getCapability(Sensors))
return model->sensorData[index - CPN_MAX_TIMERS - firmware->getCapability(RotaryEncoders)].isAvailable();
else if (model && index < resetParamCount())
return model->sensorData[index - (CPN_MAX_TIMERS + 2)].isAvailable();
return false;
}
void CustomFunctionData::convert(RadioDataConversionState & cstate)
QString CustomFunctionData::harpicToString() const
{
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
return harpicToString(param);
}
// static
QString CustomFunctionData::harpicToString(const int value)
{
return QString("%1").arg(value);
}
// static
QStringList CustomFunctionData::playSoundStringList()
{
return QStringList({ tr("Beep 1"), tr("Beep 2"), tr("Beep 3"), tr("Warn 1"), tr("Warn 2"), tr("Cheep"), tr("Ratata"), tr("Tick"),
tr("Siren"), tr("Ring"), tr("Sci Fi"), tr("Robot"), tr("Chirp"), tr("Tada"), tr("Cricket"), tr("Alarm Clock") });
}
QString CustomFunctionData::playSoundToString() const
{
return playSoundToString(param);
}
// static
QString CustomFunctionData::playSoundToString(const int value)
{
const QStringList strl = playSoundStringList();
if (value < strl.count())
return strl.at(value);
else
return QString(CPN_STR_UNKNOWN_ITEM);
}
QString CustomFunctionData::gvarAdjustModeToString() const
{
return gvarAdjustModeToString(adjustMode);
}
// static
QString CustomFunctionData::gvarAdjustModeToString(const int value)
{
switch (value) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value");
case FUNC_ADJUST_GVAR_SOURCE:
return tr("Source");
case FUNC_ADJUST_GVAR_GVAR:
return tr("Global Variable");
case FUNC_ADJUST_GVAR_INCDEC:
return tr("Inc/Decrement");
default:
return QString(CPN_STR_UNKNOWN_ITEM);
}
}
// static
AbstractStaticItemModel * CustomFunctionData::repeatItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.repeat");
for (int i = -1; i <= 60; i++) {
mdl->appendToItemList(repeatToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::playSoundItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.playsound");
for (int i = 0; i < playSoundStringList().count(); i++) {
mdl->appendToItemList(playSoundToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::harpicItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.harpic");
for (int i = 0; i <= 3; i++) {
mdl->appendToItemList(harpicToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::gvarAdjustModeItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.gvaradjustmode");
for (int i = 0; i < FUNC_ADJUST_GVAR_COUNT; i++) {
mdl->appendToItemList(gvarAdjustModeToString(i), i);
}
mdl->loadItemList();
return mdl;
}

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef CUSTOMFUNCTIONDATA_H
#define CUSTOMFUNCTIONDATA_H
#pragma once
#include "boards.h"
#include "constants.h"
@ -32,6 +31,7 @@ class Firmware;
class ModelData;
class GeneralSettings;
class RadioDataConversionState;
class AbstractStaticItemModel;
enum AssignFunc {
FuncOverrideCH1 = 0,
@ -78,7 +78,8 @@ enum GVarAdjustModes
FUNC_ADJUST_GVAR_CONSTANT,
FUNC_ADJUST_GVAR_SOURCE,
FUNC_ADJUST_GVAR_GVAR,
FUNC_ADJUST_GVAR_INCDEC
FUNC_ADJUST_GVAR_INCDEC,
FUNC_ADJUST_GVAR_COUNT
};
class CustomFunctionData {
@ -102,25 +103,33 @@ class CustomFunctionData {
unsigned int adjustMode;
int repeatParam;
void clear();
bool isEmpty() const;
QString nameToString(int index, bool globalContext = false) const;
QString funcToString(const ModelData * model = nullptr) const;
QString paramToString(const ModelData * model) const;
QString repeatToString() const;
QString enabledToString() const;
static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value);
static void populatePlaySoundParams(QStringList & qs);
static void populateHapticParams(QStringList & qs);
static bool isFuncAvailable(int index);
static int funcContext(int index);
static int resetParamCount(const ModelData * model);
static bool isResetParamAvailable(const ModelData * model, int index);
void convert(RadioDataConversionState & cstate);
void clear();
bool isEmpty() const;
QString funcToString(const ModelData * model = nullptr) const;
QString paramToString(const ModelData * model = nullptr) const;
QString repeatToString() const;
QString enabledToString() const;
QString playSoundToString() const;
QString harpicToString() const;
QString gvarAdjustModeToString() const;
static QString nameToString(const int index, const bool globalContext = false);
static QString funcToString(const AssignFunc func, const ModelData * model = nullptr);
static bool isFuncAvailable(const int index);
static int funcContext(const int index);
static QString resetToString(const int value, const ModelData * model = nullptr);
static int resetParamCount();
static bool isResetParamAvailable(const int index, const ModelData * model = nullptr);
static QString repeatToString(const int value);
static QStringList playSoundStringList();
static QString playSoundToString(const int value);
static QString harpicToString(const int value);
static QStringList gvarAdjustModeStringList();
static QString gvarAdjustModeToString(const int value);
static AbstractStaticItemModel * repeatItemModel();
static AbstractStaticItemModel * playSoundItemModel();
static AbstractStaticItemModel * harpicItemModel();
static AbstractStaticItemModel * gvarAdjustModeItemModel();
};
#endif // CUSTOMFUNCTIONDATA_H

View file

@ -18,121 +18,17 @@
* GNU General Public License for more details.
*/
#include "io_data.h"
#include "radiodata.h" // for RadioData::getElementName
#include "flightmodedata.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
/*
* ExpoData
*/
void ExpoData::convert(RadioDataConversionState & cstate)
void FlightModeData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("INP"), 3);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
cstate.setComponent("FMD", 2);
cstate.setSubComp(nameToString(cstate.subCompIdx));
swtch.convert(cstate);
}
bool ExpoData::isEmpty() const
{
return (chn == 0 && mode == INPUT_MODE_NONE);
}
/*
* MixData
*/
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool MixData::isEmpty() const
{
return (destCh == 0);
}
/*
* LimitData
*/
QString LimitData::minToString() const
{
return QString::number((qreal)min/10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max/10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset/10, 'f', 1);
}
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
bool LimitData::isEmpty() const
{
return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0' && !curve.isSet());
}
/*
* CurveData
*/
CurveData::CurveData()
{
clear();
}
void CurveData::clear(int count)
{
memset(this, 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i=0; i<count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}
/*
* FlightModeData
*/
void FlightModeData::clear(const int phaseIdx)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
@ -149,13 +45,6 @@ QString FlightModeData::nameToString(int phaseIdx) const
return RadioData::getElementName(tr("FM"), phaseIdx, name); // names are zero-based, FM0, FM1, etc
}
void FlightModeData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent("FMD", 2);
cstate.setSubComp(nameToString(cstate.subCompIdx));
swtch.convert(cstate);
}
bool FlightModeData::isEmpty(int phaseIdx) const
{
if (name[0] != '\0' || swtch.isSet() || fadeIn != 0 || fadeOut != 0)

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "constants.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
#define FLIGHTMODE_NAME_LEN 10
#define RENC_MAX_VALUE 1024
#define RENC_MIN_VALUE -RENC_MAX_VALUE
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[FLIGHTMODE_NAME_LEN + 1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void convert(RadioDataConversionState & cstate);
void clear(const int phaseIdx);
bool isEmpty(int phaseIdx) const;
QString nameToString(int phaseIdx) const;
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
bool isREncEmpty(int phaseIdx, int reIdx) const;
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
int linkedGVarFlightModeZero(int phaseIdx) const;
int linkedREncFlightModeZero(int phaseIdx) const;
};

View file

@ -0,0 +1,21 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "heli_data.h"

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "rawsource.h"
#include <QtCore>
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "input_data.h"
#include "radiodataconversionstate.h"
void ExpoData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("INP"), 3);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool ExpoData::isEmpty() const
{
return (chn == 0 && mode == INPUT_MODE_NONE);
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
#define EXPODATA_NAME_LEN 10
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[EXPODATA_NAME_LEN + 1];
void convert(RadioDataConversionState & cstate);
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
bool isEmpty() const;
};

View file

@ -1,199 +0,0 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef IO_DATA_H
#define IO_DATA_H
#include "constants.h"
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
#define EXPODATA_NAME_LEN 10
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[EXPODATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
void convert(RadioDataConversionState & cstate);
bool isEmpty() const;
};
enum MltpxValue {
MLTPX_ADD=0,
MLTPX_MUL=1,
MLTPX_REP=2
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
void convert(RadioDataConversionState & cstate);
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve; //0=symmetrisch
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
unsigned int speedDown; // 0 nichts
int carryTrim;
bool noExpo;
MltpxValue mltpx; // multiplex method 0=+ 1=* 2=replace
unsigned int mixWarn; // mixer warning
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
bool isEmpty() const;
};
#define LIMITDATA_NAME_LEN 6
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
int failsafe;
char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
void clear();
bool isEmpty() const;
};
class CurvePoint {
public:
int8_t x;
int8_t y;
};
#define CURVEDATA_NAME_LEN 6
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[CURVEDATA_NAME_LEN+1];
};
#define FLIGHTMODE_NAME_LEN 10
#define RENC_MAX_VALUE 1024
#define RENC_MIN_VALUE -RENC_MAX_VALUE
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[FLIGHTMODE_NAME_LEN+1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void clear(const int phaseIdx);
QString nameToString(int phaseIdx) const;
void convert(RadioDataConversionState & cstate);
bool isEmpty(int phaseIdx) const;
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
bool isREncEmpty(int phaseIdx, int reIdx) const;
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
int linkedGVarFlightModeZero(int phaseIdx) const;
int linkedREncFlightModeZero(int phaseIdx) const;
};
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};
#endif // IO_DATA_H

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "mixdata.h"
#include "radiodataconversionstate.h"
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool MixData::isEmpty() const
{
return (destCh == 0);
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum MltpxValue {
MLTPX_ADD,
MLTPX_MUL,
MLTPX_REP
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve;
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp;
unsigned int speedDown;
int carryTrim;
bool noExpo;
MltpxValue mltpx;
unsigned int mixWarn;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN + 1];
void convert(RadioDataConversionState & cstate);
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
bool isEmpty() const;
};

View file

@ -18,15 +18,19 @@
* GNU General Public License for more details.
*/
#ifndef MODELDATA_H
#define MODELDATA_H
#pragma once
#include "constants.h"
#include "curvedata.h"
#include "customfunctiondata.h"
#include "gvardata.h"
#include "io_data.h"
#include "flightmodedata.h"
#include "heli_data.h"
#include "input_data.h"
#include "logicalswitchdata.h"
#include "mixdata.h"
#include "moduledata.h"
#include "output_data.h"
#include "sensordata.h"
#include "telem_data.h"
@ -346,5 +350,3 @@ class ModelData {
void sortMixes();
void updateResetParam(CustomFunctionData * cfd);
};
#endif // MODELDATA_H

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "output_data.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
bool LimitData::isEmpty() const
{
return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0' && !curve.isSet());
}
QString LimitData::minToString() const
{
return QString::number((qreal)min / 10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max / 10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset / 10, 'f', 1);
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "curvereference.h"
#include <QtCore>
#define LIMITDATA_NAME_LEN 6
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
int failsafe;
char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
void clear();
bool isEmpty() const;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
};

View file

@ -427,6 +427,28 @@ bool SensorData::isSourceAvailable(const ModelData * model, const int index)
return false;
}
#define RSSI_ID 0xF101
// static
bool SensorData::isRssiSensorAvailable(const ModelData * model, const int value)
{
if (value == 0)
return true;
else {
const SensorData &sensor = model->sensorData[abs(value) - 1];
return (sensor.isAvailable() && sensor.id == RSSI_ID);
}
}
// static
QString SensorData::rssiSensorToString(const ModelData * model, const int value)
{
if (value == 0)
return tr("(default)");
else
return sourceToString(model, value);
}
// static
AbstractStaticItemModel * SensorData::typeItemModel()
{

View file

@ -206,6 +206,8 @@ class SensorData {
static QString unitToString(const int value);
static QString precToString(const int value);
static QString boolToString(const bool value) { return value ? tr("Y") : tr("N"); }
static bool isRssiSensorAvailable(const ModelData * model, const int value);
static QString rssiSensorToString(const ModelData * model, const int value);
static AbstractStaticItemModel * typeItemModel();
static AbstractStaticItemModel * formulaItemModel();

View file

@ -1527,7 +1527,7 @@ Mode 4:
<string>Battery warning voltage.
This is the threashhold where the battery warning sounds.
Acceptable values are 5v..10v</string>
Acceptable values are 3v..12v</string>
</property>
<property name="prefix">
<string notr="true"/>
@ -1539,7 +1539,7 @@ Acceptable values are 5v..10v</string>
<number>1</number>
</property>
<property name="minimum">
<double>4.000000000000000</double>
<double>3.000000000000000</double>
</property>
<property name="maximum">
<double>12.000000000000000</double>
@ -1679,7 +1679,7 @@ Acceptable values are 5v..10v</string>
<number>1</number>
</property>
<property name="minimum">
<double>4.000000000000000</double>
<double>3.000000000000000</double>
</property>
<property name="maximum">
<double>16.000000000000000</double>
@ -1708,7 +1708,7 @@ Acceptable values are 5v..10v</string>
<number>1</number>
</property>
<property name="minimum">
<double>4.000000000000000</double>
<double>3.000000000000000</double>
</property>
<property name="maximum">
<double>16.000000000000000</double>

View file

@ -32,6 +32,7 @@
#include "simulatorinterface.h"
#include "simulatormainwindow.h"
#include "storage/sdcard.h"
#include "filtereditemmodels.h"
#include <QFileDialog>
#include <QLabel>
@ -117,7 +118,8 @@ void CompanionIcon::addImage(const QString & baseimage, Mode mode, State state)
* GVarGroup
*/
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step, bool allowGvars):
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model,
const int deflt, const int mini, const int maxi, const double step, FilteredItemModel * gvarModel):
QObject(),
weightGV(weightGV),
weightSB(weightSB),
@ -131,8 +133,8 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
step(step),
lock(true)
{
if (allowGvars && getCurrentFirmware()->getCapability(Gvars)) {
Helpers::populateGVCB(*weightCB, weight, model);
if (gvarModel && gvarModel->rowCount() > 0) {
weightCB->setModel(gvarModel);
connect(weightGV, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
connect(weightCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
}
@ -152,12 +154,19 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
void GVarGroup::gvarCBChanged(int state)
{
if (!lock) {
weightCB->setVisible(state);
if (weightSB)
weightSB->setVisible(!state);
if (weightGV->isChecked()) {
// set CB to +GV1
int cnt = getCurrentFirmware()->getCapability(Gvars);
if (weightCB->count() > cnt)
weightCB->setCurrentIndex(cnt);
else
weightCB->setCurrentIndex(0);
}
weightSB->setVisible(!state);
valuesChanged();
}
}
void GVarGroup::valuesChanged()
@ -168,7 +177,7 @@ void GVarGroup::valuesChanged()
else if (sb)
weight = sb->value();
else
weight = round(dsb->value()/step);
weight = round(dsb->value() / step);
emit valueChanged();
}
@ -180,7 +189,7 @@ void GVarGroup::setWeight(int val)
int tval;
if (val>maxi || val<mini) {
if (val > maxi || val < mini) {
tval = deflt;
weightGV->setChecked(true);
weightSB->hide();
@ -214,27 +223,6 @@ void GVarGroup::setWeight(int val)
* Helpers namespace functions
*/
void Helpers::populateGVCB(QComboBox & b, int value, const ModelData & model)
{
int count = getCurrentFirmware()->getCapability(Gvars);
b.clear();
for (int i=-count; i<=-1; i++) {
int16_t gval = (int16_t)(-10000+i);
b.addItem("-" + RawSource(SOURCE_TYPE_GVAR, abs(i)-1).toString(&model), gval);
}
for (int i=1; i<=count; i++) {
int16_t gval = (int16_t)(10000+i);
b.addItem(RawSource(SOURCE_TYPE_GVAR, i-1).toString(&model), gval);
}
b.setCurrentIndex(b.findData(value));
if (b.currentIndex() == -1)
b.setCurrentIndex(count);
}
// TODO: Move lookup to GVarData class (w/out combobox)
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
{

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef _HELPERS_H_
#define _HELPERS_H_
#pragma once
#include "eeprominterface.h"
#include <QCheckBox>
@ -60,12 +59,15 @@ class CompanionIcon: public QIcon {
void addImage(const QString &baseimage, Mode mode = Normal, State state = Off);
};
class FilteredItemModel;
class GVarGroup: public QObject {
Q_OBJECT
public:
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true);
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model,
const int deflt, const int mini, const int maxi, const double step = 1.0, FilteredItemModel * gvarModel = nullptr);
void setWeight(int val);
@ -101,7 +103,6 @@ class GVarGroup: public QObject {
namespace Helpers
{
void populateGvarUseCB(QComboBox *b, unsigned int phase);
void populateGVCB(QComboBox & b, int value, const ModelData & model);
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
@ -234,5 +235,3 @@ private:
};
extern Stopwatch gStopwatch;
#endif // _HELPERS_H_

View file

@ -22,42 +22,31 @@
#include "helpers.h"
#include "filtereditemmodels.h"
LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel):
LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model,
int min, int max, int deflt, FilteredItemModel * gvarModel, ModelPanel * panel):
firmware(firmware),
spinbox(new QDoubleSpinBox()),
value(value),
displayStep(0.1)
value(value)
{
Board::Type board = firmware->getBoard();
bool allowGVars = IS_HORUS_OR_TARANIS(board);
int internalStep = 1;
spinbox->setProperty("index", row);
spinbox->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
spinbox->setAccelerated(true);
spinbox->setDecimals(1);
if (firmware->getCapability(PPMUnitMicroseconds)) {
displayStep = 0.512;
spinbox->setDecimals(1);
spinbox->setSuffix("us");
}
else {
spinbox->setDecimals(0);
displayStep = 0.1;
spinbox->setSuffix("%");
}
if (deflt == 0 /*it's the offset*/) {
spinbox->setDecimals(1);
}
else {
internalStep *= 10;
}
spinbox->setSingleStep(displayStep * internalStep);
spinbox->setSingleStep(displayStep);
spinbox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
QHBoxLayout *horizontalLayout = new QHBoxLayout();
QCheckBox *gv = new QCheckBox(tr("GV"));
gv = new QCheckBox(tr("GV"));
gv->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
horizontalLayout->addWidget(gv);
QComboBox *cb = new QComboBox();
@ -65,7 +54,7 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row
horizontalLayout->addWidget(cb);
horizontalLayout->addWidget(spinbox);
tableLayout->addLayout(row, col, horizontalLayout);
gvarGroup = new GVarGroup(gv, spinbox, cb, value, model, deflt, min, max, displayStep, allowGVars);
gvarGroup = new GVarGroup(gv, spinbox, cb, value, model, deflt, min, max, displayStep, gvarModel);
QObject::connect(gvarGroup, &GVarGroup::valueChanged, panel, &ModelPanel::modified);
}
@ -84,18 +73,19 @@ void LimitsGroup::updateMinMax(int max)
if (spinbox->maximum() == 0) {
spinbox->setMinimum(-max * displayStep);
gvarGroup->setMinimum(-max);
if (value < -max) {
if (!gv->isChecked() && value < -max) {
value = -max;
}
}
if (spinbox->minimum() == 0) {
spinbox->setMaximum(max * displayStep);
gvarGroup->setMaximum(max);
if (value > max) {
if (!gv->isChecked() && value > max) {
value = max;
}
}
}
ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware),
sharedItemModels(sharedItemModels)
@ -103,8 +93,12 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
chnCapability = firmware->getCapability(Outputs);
int channelNameMaxLen = firmware->getCapability(ChannelsName);
curveFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve));
connectItemModelEvents(curveFilteredModel);
dialogFilteredItemModels = new FilteredItemModelFactory();
int crvid = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve)), "Curve");
connectItemModelEvents(dialogFilteredItemModels->getItemModel(crvid));
int gvid = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
QStringList headerLabels;
headerLabels << "#";
@ -146,13 +140,13 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
}
// Channel offset
chnOffset[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].offset, model, -1000, 1000, 0, this);
chnOffset[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].offset, model, -1000, 1000, 0, dialogFilteredItemModels->getItemModel(gvid), this);
// Channel min
chnMin[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].min, model, -model.getChannelsMax() * 10, 0, -1000, this);
chnMin[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].min, model, -model.getChannelsMax() * 10, 0, -1000, dialogFilteredItemModels->getItemModel(gvid), this);
// Channel max
chnMax[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].max, model, 0, model.getChannelsMax() * 10, 1000, this);
chnMax[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].max, model, 0, model.getChannelsMax() * 10, 1000, dialogFilteredItemModels->getItemModel(gvid), this);
// Channel inversion
invCB[i] = new QComboBox(this);
@ -165,7 +159,7 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
curveCB[i] = new QComboBox(this);
curveCB[i]->setProperty("index", i);
curveCB[i]->setModel(curveFilteredModel);
curveCB[i]->setModel(dialogFilteredItemModels->getItemModel(crvid));
connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited()));
tableLayout->addWidget(i, col++, curveCB[i]);
}
@ -213,7 +207,7 @@ ChannelsPanel::~ChannelsPanel()
delete centerSB[i];
delete symlimitsChk[i];
}
delete curveFilteredModel;
delete dialogFilteredItemModels;
}
void ChannelsPanel::symlimitsEdited()
@ -241,12 +235,11 @@ void ChannelsPanel::nameEdited()
void ChannelsPanel::refreshExtendedLimits()
{
int channelMax = model->getChannelsMax();
int channelMax = model->getChannelsMax() * 10;
for (int i = 0 ; i < CPN_MAX_CHNOUT; i++) {
chnOffset[i]->updateMinMax(10 * channelMax);
chnMin[i]->updateMinMax(10 * channelMax);
chnMax[i]->updateMinMax(10 * channelMax);
chnMin[i]->updateMinMax(channelMax);
chnMax[i]->updateMinMax(channelMax);
}
emit modified();
}

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef _CHANNELS_H_
#define _CHANNELS_H_
#pragma once
#include "helpers.h"
#include "modeledit.h"
@ -27,7 +26,7 @@
#include <QtCore>
class CompoundItemModelFactory;
class FilteredItemModel;
class FilteredItemModelFactory;
constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel";
@ -38,7 +37,8 @@ class LimitsGroup
Q_DECLARE_TR_FUNCTIONS(LimitsGroup)
public:
LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel=NULL);
LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model,
int min, int max, int deflt, FilteredItemModel * gvarModel, ModelPanel * panel = nullptr);
~LimitsGroup();
void setValue(int val);
@ -50,6 +50,7 @@ class LimitsGroup
GVarGroup *gvarGroup;
int &value;
double displayStep;
QCheckBox *gv;
};
class ChannelsPanel : public ModelPanel
@ -57,7 +58,8 @@ class ChannelsPanel : public ModelPanel
Q_OBJECT
public:
ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
CompoundItemModelFactory * sharedItemModels);
virtual ~ChannelsPanel();
public slots:
@ -101,9 +103,7 @@ class ChannelsPanel : public ModelPanel
int selectedIndex;
int chnCapability;
CompoundItemModelFactory *sharedItemModels;
FilteredItemModel *curveFilteredModel;
void updateItemModels();
void connectItemModelEvents(const FilteredItemModel * itemModel);
FilteredItemModelFactory *dialogFilteredItemModels;
};
#endif // _CHANNELS_H_

View file

@ -19,53 +19,11 @@
*/
#include "customfunctions.h"
#include "filtereditemmodels.h"
#include "helpers.h"
#include "appdata.h"
#include <TimerEdit>
RepeatComboBox::RepeatComboBox(QWidget *parent, int & repeatParam):
QComboBox(parent),
repeatParam(repeatParam)
{
unsigned int step = 1;
int value = repeatParam/step;
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
if (step == 1) {
addItem(tr("Played once, not during startup"), -1);
value++;
}
addItem(tr("No repeat"), 0);
for (unsigned int i = step; i <= 60; i += step) {
addItem(tr("%1s").arg(i), i);
}
setCurrentIndex(value);
connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onIndexChanged(int)));
}
void RepeatComboBox::onIndexChanged(int index)
{
repeatParam = itemData(index).toInt();
emit modified();
}
void RepeatComboBox::update()
{
unsigned int step = 1;
int value = repeatParam/step;
if (step == 1) {
value++;
}
setCurrentIndex(value);
}
CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware,
CompoundItemModelFactory * sharedItemModels):
GenericPanel(parent, model, generalSettings, firmware),
@ -77,18 +35,41 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
lock = true;
fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions);
rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext);
connectItemModelEvents(rawSwitchFilteredModel);
tabModelFactory = new CompoundItemModelFactory(&generalSettings, model);
playSoundId = tabModelFactory->registerItemModel(CustomFunctionData::playSoundItemModel());
harpicId = tabModelFactory->registerItemModel(CustomFunctionData::harpicItemModel());
repeatId = tabModelFactory->registerItemModel(CustomFunctionData::repeatItemModel());
gvarAdjustModeId = tabModelFactory->registerItemModel(CustomFunctionData::gvarAdjustModeItemModel());
rawSourceAllModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource));
connectItemModelEvents(rawSourceAllModel);
tabFilterFactory = new FilteredItemModelFactory();
rawSourceInputsModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::InputSourceGroups);
connectItemModelEvents(rawSourceInputsModel);
funcActionsId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CustomFuncAction),
model ? CustomFunctionData::AllFunctionContexts : CustomFunctionData::GlobalFunctionsContext),
"Function Actions");
connectItemModelEvents(tabFilterFactory->getItemModel(funcActionsId));
rawSourceGVarsModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::GVarsGroup);
connectItemModelEvents(rawSourceGVarsModel);
funcResetParamId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CustomFuncResetParam)),
"Reset Params");
connectItemModelEvents(tabFilterFactory->getItemModel(funcResetParamId));
rawSwitchId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext),
"RawSwitch");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSwitchId));
rawSourceAllId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource)),
"RawSource All");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSourceAllId));
rawSourceInputsId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource),
RawSource::InputSourceGroups),
"RawSource Inputs");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSourceInputsId));
rawSourceGVarsId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource),
RawSource::GVarsGroup),
"RawSource GVars");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSourceGVarsId));
if (!firmware->getCapability(VoicesAsNumbers)) {
tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength));
@ -118,7 +99,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
playIcon.addImage("stop.png", QIcon::Normal, QIcon::On);
QStringList headerLabels;
headerLabels << "#" << tr("Switch") << tr("Action") << tr("Parameters") << tr("Enable");
headerLabels << "#" << tr("Switch") << tr("Action") << tr("Parameters") << "";
TableLayout * tableLayout = new TableLayout(this, fswCapability, headerLabels);
for (int i = 0; i < fswCapability; i++) {
@ -135,32 +116,26 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
tableLayout->addWidget(i, 0, label);
// s1.report("label");
// The switch
fswtchSwtch[i] = new QComboBox(this);
fswtchSwtch[i]->setModel(rawSwitchFilteredModel);
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
fswtchSwtch[i]->setProperty("index", i);
fswtchSwtch[i]->setModel(tabFilterFactory->getItemModel(rawSwitchId));
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
fswtchSwtch[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
fswtchSwtch[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
fswtchSwtch[i]->setMaxVisibleItems(10);
connect(fswtchSwtch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
tableLayout->addWidget(i, 1, fswtchSwtch[i]);
// s1.report("switch");
// The function
fswtchFunc[i] = new QComboBox(this);
if (!i) {
populateFuncCB(fswtchFunc[i], functions[i].func);
}
else {
fswtchFunc[i]->setModel(fswtchFunc[0]->model());
fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(functions[i].func));
}
fswtchFunc[i]->setProperty("index", i);
fswtchFunc[i]->setModel(tabFilterFactory->getItemModel(funcActionsId));
fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(functions[i].func));
fswtchFunc[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
connect(fswtchFunc[i], SIGNAL(currentIndexChanged(int)), this, SLOT(functionEdited()));
tableLayout->addWidget(i, 2, fswtchFunc[i]);
// s1.report("func");
// The parameters
QHBoxLayout * paramLayout = new QHBoxLayout();
@ -168,15 +143,15 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
fswtchGVmode[i] = new QComboBox(this);
fswtchGVmode[i]->setProperty("index", i);
populateGVmodeCB(fswtchGVmode[i], functions[i].adjustMode);
fswtchGVmode[i]->setModel(tabModelFactory->getItemModel(gvarAdjustModeId));
fswtchGVmode[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
connect(fswtchGVmode[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
paramLayout->addWidget(fswtchGVmode[i]);
fswtchParamGV[i] = new QCheckBox(this);
fswtchParamGV[i]->setProperty("index", i);
fswtchParamGV[i]->setText("GV");
fswtchParamGV[i]->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
fswtchParamGV[i]->setText(tr("GV"));
fswtchParamGV[i]->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
connect(fswtchParamGV[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited()));
paramLayout->addWidget(fswtchParamGV[i]);
@ -207,15 +182,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
connect(fswtchParamArmT[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
connect(fswtchParamArmT[i], SIGNAL(editTextChanged ( const QString)), this, SLOT(customFunctionEdited()));
fswtchBLcolor[i] = new QSlider(this);
fswtchBLcolor[i]->setProperty("index", i);
fswtchBLcolor[i]->setMinimum(0);
fswtchBLcolor[i]->setMaximum(100);
fswtchBLcolor[i]->setSingleStep(1);
fswtchBLcolor[i]->setOrientation(Qt::Horizontal);
paramLayout->addWidget(fswtchBLcolor[i]);
connect(fswtchBLcolor[i], SIGNAL(sliderReleased()), this, SLOT(customFunctionEdited()));
playBT[i] = new QToolButton(this);
playBT[i]->setProperty("index", i);
playBT[i]->setIcon(playIcon);
@ -225,9 +191,13 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
QHBoxLayout * repeatLayout = new QHBoxLayout();
tableLayout->addLayout(i, 4, repeatLayout);
fswtchRepeat[i] = new RepeatComboBox(this, functions[i].repeatParam);
fswtchRepeat[i] = new QComboBox(this);
fswtchRepeat[i]->setProperty("index", i);
fswtchRepeat[i]->setModel(tabModelFactory->getItemModel(repeatId));
fswtchRepeat[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
fswtchRepeat[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
repeatLayout->addWidget(fswtchRepeat[i], i + 1);
connect(fswtchRepeat[i], SIGNAL(modified()), this, SLOT(onRepeatModified()));
connect(fswtchRepeat[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
fswtchEnable[i] = new QCheckBox(this);
fswtchEnable[i]->setProperty("index", i);
@ -250,10 +220,8 @@ CustomFunctionsPanel::~CustomFunctionsPanel()
{
if (mediaPlayer)
stopSound(mediaPlayerCurrent);
delete rawSwitchFilteredModel;
delete rawSourceAllModel;
delete rawSourceInputsModel;
delete rawSourceGVarsModel;
delete tabModelFactory;
delete tabFilterFactory;
}
void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state)
@ -333,7 +301,6 @@ void CustomFunctionsPanel::toggleSound(bool play)
#define CUSTOM_FUNCTION_ENABLE (1<<6)
#define CUSTOM_FUNCTION_REPEAT (1<<7)
#define CUSTOM_FUNCTION_PLAY (1<<8)
#define CUSTOM_FUNCTION_BL_COLOR (1<<9)
#define CUSTOM_FUNCTION_SHOW_FUNC (1<<10)
@ -363,11 +330,6 @@ void CustomFunctionsPanel::functionEdited()
}
}
void CustomFunctionsPanel::onRepeatModified()
{
emit modified();
}
void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
{
CustomFunctionData & cfn = functions[i];
@ -414,8 +376,8 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) {
int gvidx = func - FuncAdjustGV1;
if (modified)
cfn.adjustMode = fswtchGVmode[i]->currentIndex();
fswtchGVmode[i]->setCurrentIndex(cfn.adjustMode);
cfn.adjustMode = fswtchGVmode[i]->currentData().toInt();
fswtchGVmode[i]->setCurrentIndex(fswtchGVmode[i]->findData(cfn.adjustMode));
widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE;
if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) {
if (modified)
@ -468,8 +430,10 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
}
else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic) {
if (func != FuncBackgroundMusic) {
if (modified)
cfn.repeatParam = fswtchRepeat[i]->currentData().toInt();
widgetsMask |= CUSTOM_FUNCTION_REPEAT;
fswtchRepeat[i]->update();
fswtchRepeat[i]->setCurrentIndex(fswtchRepeat[i]->findData(cfn.repeatParam));
}
if (func == FuncPlayValue) {
if (modified)
@ -493,7 +457,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
if (modified) {
if (fswtchParamGV[i]->isChecked()) {
fswtchParam[i]->setMinimum(1);
cfn.param = std::min(fswtchParam[i]->value(),5.0)+(fswtchParamGV[i]->isChecked() ? 250 : 0);
cfn.param = std::min(fswtchParam[i]->value(), 5.0) + (fswtchParamGV[i]->isChecked() ? 250 : 0);
}
else {
cfn.param = fswtchParam[i]->value();
@ -577,7 +541,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
fswtchEnable[i]->setChecked(false);
fswtchRepeat[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_REPEAT);
fswtchGVmode[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_MODE);
fswtchBLcolor[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_BL_COLOR);
playBT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_PLAY);
}
@ -653,77 +616,43 @@ void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos)
contextMenu.exec(globalPos);
}
void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
{
b->clear();
for (unsigned int i = 0; i < FuncCount; i++) {
if (((i >= FuncOverrideCH1 && i <= FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) ||
((i == FuncVolume || i == FuncBackgroundMusic || i == FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) ||
((i == FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) ||
((i == FuncPlayHaptic) && !firmware->getCapability(Haptic)) ||
((i == FuncPlayBoth) && !firmware->getCapability(HasBeeper)) ||
((i == FuncLogs) && !firmware->getCapability(HasSDLogs)) ||
((i == FuncSetTimer3) && firmware->getCapability(Timers) < 3) ||
((i == FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) ||
((i >= FuncRangeCheckInternalModule && i <= FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) ||
((i >= FuncAdjustGV1 && i <= FuncAdjustGVLast) && (!model || !firmware->getCapability(Gvars)))
) {
// skipped
continue;
}
else {
b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i);
if (i == value) {
b->setCurrentIndex(b->count() - 1);
}
}
}
}
void CustomFunctionsPanel::populateGVmodeCB(QComboBox *b, unsigned int value)
{
b->clear();
b->addItem(tr("Value"));
b->addItem(tr("Source"));
b->addItem(tr("GVAR"));
b->addItem(tr("Increment"));
b->setCurrentIndex(value);
}
void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode)
{
QStringList qs;
b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model
if (function == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs);
b->addItems(qs);
b->setCurrentIndex(value);
b->setModel(tabModelFactory->getItemModel(playSoundId));
b->setCurrentIndex(b->findData(value));
}
else if (function == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs);
b->addItems(qs);
b->setCurrentIndex(value);
b->setModel(tabModelFactory->getItemModel(harpicId));
b->setCurrentIndex(b->findData(value));
}
else if (function == FuncReset) {
CustomFunctionData::populateResetParams(model, b, value);
b->setModel(tabFilterFactory->getItemModel(funcResetParamId));
b->setCurrentIndex(b->findData(value));
}
else if (function == FuncVolume || function == FuncBacklight) {
b->setModel(rawSourceInputsModel);
b->setModel(tabFilterFactory->getItemModel(rawSourceInputsId));
b->setCurrentIndex(b->findData(value));
}
else if (function == FuncPlayValue) {
b->setModel(rawSourceAllModel);
b->setModel(tabFilterFactory->getItemModel(rawSourceAllId));
b->setCurrentIndex(b->findData(value));
}
else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) {
switch (adjustmode) {
case 1:
b->setModel(rawSourceInputsModel);
b->setModel(tabFilterFactory->getItemModel(rawSourceInputsId));
b->setCurrentIndex(b->findData(value));
if (b->currentIndex() < 0)
b->setCurrentIndex(0);
break;
case 2:
b->setModel(rawSourceGVarsModel);
b->setModel(tabFilterFactory->getItemModel(rawSourceGVarsId));
b->setCurrentIndex(b->findData(value));
if (b->currentIndex() < 0)
b->setCurrentIndex(0);
break;
}
}
@ -828,7 +757,7 @@ bool CustomFunctionsPanel::moveUpAllowed() const
return selectedIndex > 0;
}
void CustomFunctionsPanel::connectItemModelEvents(const FilteredItemModel * itemModel)
void CustomFunctionsPanel::connectItemModelEvents(FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &CustomFunctionsPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &CustomFunctionsPanel::onItemModelUpdateComplete);

View file

@ -18,38 +18,19 @@
* GNU General Public License for more details.
*/
#ifndef _CUSTOMFUNCTIONS_H_
#define _CUSTOMFUNCTIONS_H_
#pragma once
#include "modeledit.h"
#include "eeprominterface.h"
#include "compounditemmodels.h"
#include "filtereditemmodels.h"
#include <QMediaPlayer>
class CompoundItemModelFactory;
class FilteredItemModel;
class TimerEdit;
constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function";
class RepeatComboBox: public QComboBox
{
Q_OBJECT
public:
RepeatComboBox(QWidget * parent, int & repeatParam);
void update();
signals:
void modified();
private slots:
void onIndexChanged(int);
protected:
int & repeatParam;
};
class CustomFunctionsPanel : public GenericPanel
{
Q_OBJECT
@ -68,7 +49,6 @@ class CustomFunctionsPanel : public GenericPanel
void functionEdited();
void onCustomContextMenuRequested(QPoint pos);
void refreshCustomFunction(int index, bool modified=false);
void onRepeatModified();
bool playSound(int index);
void stopSound(int index);
void toggleSound(bool play);
@ -87,8 +67,6 @@ class CustomFunctionsPanel : public GenericPanel
void onItemModelUpdateComplete();
private:
void populateFuncCB(QComboBox *b, unsigned int value);
void populateGVmodeCB(QComboBox *b, unsigned int value);
void populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode=0);
bool hasClipboardData(QByteArray * data = nullptr) const;
bool insertAllowed() const;
@ -96,12 +74,20 @@ class CustomFunctionsPanel : public GenericPanel
bool moveUpAllowed() const;
void swapData(int idx1, int idx2);
void resetCBsAndRefresh(int idx);
void connectItemModelEvents(const FilteredItemModel * itemModel);
void connectItemModelEvents(FilteredItemModel * itemModel);
FilteredItemModel * rawSwitchFilteredModel;
FilteredItemModel * rawSourceAllModel;
FilteredItemModel * rawSourceInputsModel;
FilteredItemModel * rawSourceGVarsModel;
CompoundItemModelFactory * tabModelFactory;
FilteredItemModelFactory * tabFilterFactory;
int funcActionsId;
int funcResetParamId;
int rawSwitchId;
int rawSourceAllId;
int rawSourceInputsId;
int rawSourceGVarsId;
int playSoundId;
int harpicId;
int repeatId;
int gvarAdjustModeId;
QSet<QString> tracksSet;
QSet<QString> scriptsSet;
@ -115,14 +101,11 @@ class CustomFunctionsPanel : public GenericPanel
QComboBox * fswtchParamT[CPN_MAX_SPECIAL_FUNCTIONS];
QComboBox * fswtchParamArmT[CPN_MAX_SPECIAL_FUNCTIONS];
QCheckBox * fswtchEnable[CPN_MAX_SPECIAL_FUNCTIONS];
RepeatComboBox * fswtchRepeat[CPN_MAX_SPECIAL_FUNCTIONS];
QComboBox * fswtchRepeat[CPN_MAX_SPECIAL_FUNCTIONS];
QComboBox * fswtchGVmode[CPN_MAX_SPECIAL_FUNCTIONS];
QSlider * fswtchBLcolor[CPN_MAX_SPECIAL_FUNCTIONS];
QMediaPlayer * mediaPlayer;
int selectedIndex;
int fswCapability;
int modelsUpdateCnt;
};
#endif // _CUSTOMFUNCTIONS_H_

View file

@ -50,8 +50,11 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings)));
QRegExp rx(CHAR_FOR_NAMES_REGEX);
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100);
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100);
id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100, 1.0,
dialogFilteredItemModels->getItemModel(id));
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100, 1.0,
dialogFilteredItemModels->getItemModel(id));
curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels,
firmware->getCapability(HasInputDiff) ? 0 : FilteredItemModel::PositiveFilter);

View file

@ -351,6 +351,9 @@ void InputsPanel::expoOpen(QListWidgetItem *item)
if (!item)
item = ExposlistWidget->currentItem();
if (item == nullptr)
return;
int idx = item->data(Qt::UserRole).toByteArray().at(0);
if (idx < 0) {
int ch = -idx - 1;
@ -368,7 +371,11 @@ void InputsPanel::expoOpen(QListWidgetItem *item)
void InputsPanel::expoAdd()
{
int index = ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
QListWidgetItem *item = ExposlistWidget->currentItem();
if (item == nullptr)
return;
int index = item->data(Qt::UserRole).toByteArray().at(0);
if (index < 0) { // if empty then return relevant index
expoOpen();

View file

@ -55,9 +55,13 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue()));
int limit = firmware->getCapability(OffsetWeight);
id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit, 1.0,
dialogFilteredItemModels->getItemModel(id));
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit, 1.0,
dialogFilteredItemModels->getItemModel(id));
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit);
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit);
curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels,
firmware->getCapability(HasMixerExpo) ? 0 : FilteredItemModel::PositiveFilter);
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model,

View file

@ -354,7 +354,11 @@ void MixesPanel::mixersDuplicate()
void MixesPanel::mixerOpen()
{
int idx = mixersListWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
QListWidgetItem *item = mixersListWidget->currentItem();
if (item == nullptr)
return;
int idx = item->data(Qt::UserRole).toByteArray().at(0);
if(idx < 0) {
int i = -idx;
idx = getMixerIndex(i); //get mixer index to insert
@ -371,7 +375,11 @@ void MixesPanel::mixerOpen()
void MixesPanel::mixerHighlight()
{
int idx = mixersListWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
QListWidgetItem *item = mixersListWidget->currentItem();
if (item == nullptr)
return;
int idx = item->data(Qt::UserRole).toByteArray().at(0);
int dest;
if (idx<0) {
dest = -idx;

View file

@ -62,6 +62,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw
sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam);
sharedItemModels->addItemModel(AbstractItemModel::IMID_TeleSource);
sharedItemModels->addItemModel(AbstractItemModel::IMID_RssiSource);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CurveRefType);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CurveRefFunc);

View file

@ -701,6 +701,7 @@ void ModulePanel::onProtocolChanged(int index)
module.protocol = ui->protocol->itemData(index).toInt();
module.channelsCount = module.getMaxChannelCount();
update();
emit updateItemModels();
emit modified();
}
}
@ -801,6 +802,7 @@ void ModulePanel::onMultiProtocolChanged(int index)
module.subType = std::min(module.subType, maxSubTypes - 1);
module.channelsCount = module.getMaxChannelCount();
update();
emit updateItemModels();
emit modified();
lock = false;
}
@ -1251,6 +1253,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i);
ui->modulesLayout->addWidget(modules[i]);
connect(modules[i], &ModulePanel::modified, this, &SetupPanel::modified);
connect(modules[i], &ModulePanel::updateItemModels, this, &SetupPanel::onModuleUpdateItemModels);
connect(this, &SetupPanel::extendedLimitsToggled, modules[i], &ModulePanel::onExtendedLimitsToggled);
}
@ -1798,3 +1801,8 @@ void SetupPanel::updateItemModels()
{
sharedItemModels->update(AbstractItemModel::IMUE_Timers);
}
void SetupPanel::onModuleUpdateItemModels()
{
sharedItemModels->update(AbstractItemModel::IMUE_Modules);
}

View file

@ -81,6 +81,7 @@ class ModulePanel : public ModelPanel
signals:
void channelsRangeChanged();
void failsafeModified(unsigned index);
void updateItemModels();
private slots:
void setupFailsafes();
@ -175,6 +176,7 @@ class SetupPanel : public ModelPanel
void onTimerNameChanged();
void onItemModelAboutToBeUpdated();
void onItemModelUpdateComplete();
void onModuleUpdateItemModels();
private:
Ui::Setup *ui;

View file

@ -35,6 +35,7 @@ constexpr char FIM_SENSORFORMULA[] {"Sensor.Formula"};
constexpr char FIM_SENSORCELLINDEX[] {"Sensor.CellIndex"};
constexpr char FIM_SENSORUNIT[] {"Sensor.Unit"};
constexpr char FIM_SENSORPRECISION[] {"Sensor.Precision"};
constexpr char FIM_RSSISOURCE[] {"Rssi Source"};
TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings,
Firmware * firmware, const bool & parentLock, FilteredItemModelFactory * panelFilteredItemModels):
@ -111,7 +112,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
lock = false;
if (IS_TARANIS(firmware->getBoard())) {
QSet<QString> scriptsSet = getFilesSet(g.profile[g.id()].sdPath() + "/SCRIPTS/TELEMETRY", QStringList() << "*.lua", 8);
QSet<QString> scriptsSet = getFilesSet(g.profile[g.id()].sdPath() + "/SCRIPTS/TELEMETRY", QStringList() << "*.lua", 6);
Helpers::populateFileComboBox(ui->scriptName, scriptsSet, screen.body.script.filename);
connect(ui->scriptName, SIGNAL(currentIndexChanged(int)), this, SLOT(scriptNameEdited()));
connect(ui->scriptName, SIGNAL(editTextChanged ( const QString)), this, SLOT(scriptNameEdited()));
@ -696,6 +697,11 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
FIM_TELEPOSSRC);
connectItemModelEvents(id);
id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RssiSource)),
FIM_RSSISOURCE);
connectItemModelEvents(id);
id = panelItemModels->registerItemModel(SensorData::typeItemModel());
panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORTYPE);
@ -813,12 +819,14 @@ void TelemetryPanel::setup()
ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this);
ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled);
ui->rssiAlarmWarningSB->setRange(45 - 30, 45 + 30);
ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning);
ui->rssiAlarmCriticalSB->setRange(42 - 30, 42 + 30);
ui->rssiAlarmCriticalSB->setValue(model->rssiAlarms.critical);
ui->rssiSourceLabel->show();
ui->rssiSourceLabel->setText(tr("Source"));
ui->rssiSourceCB->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC));
ui->rssiSourceCB->setModel(panelFilteredItemModels->getItemModel(FIM_RSSISOURCE));
ui->rssiSourceCB->setField(model->rssiSource, this);
ui->rssiSourceCB->show();

File diff suppressed because it is too large Load diff

View file

@ -161,7 +161,7 @@ const char * const unitsFilenames[] = {
"hertz",
"ms",
"us",
"spare4",
"km",
"spare5",
"spare6",
"spare7",

View file

@ -699,11 +699,11 @@ int cliTrace(const char ** argv)
int cliStackInfo(const char ** argv)
{
serialPrint("[MAIN] %d available / %d", stackAvailable(), stackSize());
serialPrint("[MENUS] %d available / %d", menusStack.available(), menusStack.size());
serialPrint("[MIXER] %d available / %d", mixerStack.available(), mixerStack.size());
serialPrint("[AUDIO] %d available / %d", audioStack.available(), audioStack.size());
serialPrint("[CLI] %d available / %d", cliStack.available(), cliStack.size());
serialPrint("[MAIN] %d available / %d bytes", stackAvailable()*4, stackSize()*4);
serialPrint("[MENUS] %d available / %d bytes", menusStack.available()*4, menusStack.size());
serialPrint("[MIXER] %d available / %d bytes", mixerStack.available()*4, mixerStack.size());
serialPrint("[AUDIO] %d available / %d bytes", audioStack.available()*4, audioStack.size());
serialPrint("[CLI] %d available / %d bytes", cliStack.available()*4, cliStack.size());
return 0;
}

View file

@ -278,6 +278,7 @@ enum TelemetryProtocol
PROTOCOL_TELEMETRY_FLYSKY_IBUS,
PROTOCOL_TELEMETRY_HITEC,
PROTOCOL_TELEMETRY_HOTT,
PROTOCOL_TELEMETRY_MLINK,
PROTOCOL_TELEMETRY_MULTIMODULE,
PROTOCOL_TELEMETRY_AFHDS3,
PROTOCOL_TELEMETRY_GHOST,
@ -318,8 +319,8 @@ enum TelemetryUnit {
UNIT_HERTZ,
UNIT_MS,
UNIT_US,
UNIT_MAX = UNIT_US,
UNIT_SPARE4,
UNIT_KM,
UNIT_MAX = UNIT_KM,
UNIT_SPARE5,
UNIT_SPARE6,
UNIT_SPARE7,

View file

@ -1538,40 +1538,35 @@ void menuModelSetup(event_t event)
{
#if defined(MULTIMODULE)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
const char * title = getMultiOptionTitle(moduleIdx);
lcdDrawText(INDENT_WIDTH, y, title);
if (title == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
if (status.isValid()) {
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
if (attr && status.optionDisp == 2) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr) {
lcdDrawText(INDENT_WIDTH, y, pdef->optionsstr);
if (attr && pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
}
int8_t min, max;
getMultiOptionValues(multi_proto, min, max);
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
if (title == STR_MULTI_RFPOWER) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
min = 0;
max = 15;
}
else if (title == STR_MULTI_TELEMETRY) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_TELEMETRY_MODE, optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
else if (title == STR_MULTI_WBUS) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_WBUS_MODE, optionValue, LEFT | attr);
min = 0;
max = 1;
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
optionValue = optionValue & 0x01;

View file

@ -1294,38 +1294,34 @@ void menuModelSetup(event_t event)
#if defined(MULTIMODULE)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
const char * title = getMultiOptionTitle(moduleIdx);
lcdDrawText(INDENT_WIDTH, y, title);
if (title == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol();
if (status.isValid()) {
lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
if (attr && status.optionDisp == 2) {
lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr)
lcdDrawText(INDENT_WIDTH, y, pdef->optionsstr);
if (pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
int8_t min, max;
getMultiOptionValues(multi_proto, min, max);
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
if (title == STR_MULTI_RFPOWER) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
}
else if (title == STR_MULTI_TELEMETRY) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_TELEMETRY_MODE, optionValue, LEFT | attr);
}
else if (title == STR_MULTI_WBUS) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_WBUS_MODE, optionValue, LEFT | attr);
min = 0;
max = 1;
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
optionValue = optionValue & 0x01;
editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event);

View file

@ -1676,34 +1676,33 @@ bool menuModelSetup(event_t event)
{
#if defined(MULTIMODULE)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
const char * title = getMultiOptionTitle(moduleIdx);
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, title);
if (title == STR_MULTI_RFTUNE) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
if (status.isValid()) {
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
if (attr && status.optionDisp == 2) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
}
else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr) {
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, pdef->optionsstr);
if (attr && pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
}
}
int8_t min, max;
getMultiOptionValues(multi_proto, min, max);
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
if (title == STR_MULTI_RFPOWER) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
min = 0;
max = 15;
}
else if (title == STR_MULTI_TELEMETRY) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_TELEMETRY_MODE, optionValue, LEFT | attr);
}
else if (title == STR_MULTI_WBUS) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_WBUS_MODE, optionValue, LEFT | attr);
min = 0;
max = 1;
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
optionValue = optionValue & 0x01;
@ -1715,6 +1714,7 @@ bool menuModelSetup(event_t event)
else
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
}
if (attr) {
CHECK_INCDEC_MODELVAR(event, optionValue, min, max);
if (checkIncDec_Ret) {

View file

@ -994,9 +994,15 @@ const char* mm_options_strings::options[] = {
STR_MULTI_SERVOFREQ,
STR_MULTI_MAX_THROW,
STR_MULTI_RFCHAN,
STR_MULTI_RFPOWER
STR_MULTI_RFPOWER,
STR_MULTI_WBUS
};
const uint8_t getMaxMultiOptions()
{
return DIM(mm_options_strings::options);
}
const mm_protocol_definition multi_protocols[] = {
// Protocol as defined in pulses\modules_constants.h, number of sub_protocols - 1, Failsafe supported, Disable channel mapping supported, Subtype string, Option type
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, true, STR_SUBTYPE_FLYSKY, nullptr},
@ -1091,3 +1097,22 @@ void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, Lcd
else
lcdDrawMMM(x, y, flags);
}
#if defined(MULTIMODULE)
const char * getMultiOptionTitle(uint8_t moduleIdx)
{
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
if (status.isValid()) {
if (status.optionDisp >= getMaxMultiOptions()) {
status.optionDisp = 1; // Unknown options are defaulted to type 1 (basic option)
}
return mm_options_strings::options[status.optionDisp];
}
else {
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
return pdef->optionsstr;
}
}
#endif

View file

@ -319,6 +319,7 @@ inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) {
}
void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags);
const char * getMultiOptionTitle(uint8_t moduleIdx);
const char * writeScreenshot();

View file

@ -1411,7 +1411,10 @@ Get RSSI value as well as low and critical RSSI alarm levels (in dB)
*/
static int luaGetRSSI(lua_State * L)
{
if (TELEMETRY_STREAMING())
lua_pushunsigned(L, min((uint8_t)99, TELEMETRY_RSSI()));
else
lua_pushunsigned(L, 0);
lua_pushunsigned(L, g_model.rssiAlarms.getWarningRssi());
lua_pushunsigned(L, g_model.rssiAlarms.getCriticalRssi());
return 3;
@ -2038,6 +2041,7 @@ const luaR_value_entry opentxConstants[] = {
{"UNIT_KMH", UNIT_KMH },
{"UNIT_MPH", UNIT_MPH },
{"UNIT_METERS", UNIT_METERS },
{"UNIT_KM", UNIT_KM },
{"UNIT_FEET", UNIT_FEET },
{"UNIT_CELSIUS", UNIT_CELSIUS },
{"UNIT_FAHRENHEIT", UNIT_FAHRENHEIT },

View file

@ -42,6 +42,8 @@ struct mm_options_strings {
static const char* options[];
};
const uint8_t getMaxMultiOptions();
struct mm_protocol_definition {
uint8_t protocol;
uint8_t maxSubtype;
@ -671,10 +673,6 @@ inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max)
min = -1;
max = 84;
break;
case MODULE_SUBTYPE_MULTI_FRSKY_R9:
min = 0; // 10mW
max = 5; // 300mW
break;
default:
min = -128;
max = 127;

View file

@ -168,7 +168,7 @@ template<int SIZE>
}
#endif
#define RTOS_MS_PER_TICK ((CFG_CPU_FREQ / CFG_SYSTICK_FREQ) / (CFG_CPU_FREQ / 1000)) // RTOS timer tick length in ms (currently 2)
#define RTOS_MS_PER_TICK (1000 / CFG_SYSTICK_FREQ) // RTOS timer tick length in ms (currently 1 for STM32, 2 for others)
typedef OS_TID RTOS_TASK_HANDLE;
typedef OS_MutexID RTOS_MUTEX_HANDLE;

View file

@ -148,7 +148,7 @@ endif()
if(MULTIMODULE)
add_definitions(-DMULTIMODULE)
set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/mlink.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
endif()
if(CROSSFIRE)

View file

@ -420,9 +420,9 @@
#define AUX_SERIAL_USART_IRQn USART3_IRQn
#define AUX_SERIAL_DMA_Stream_RX DMA1_Stream1
#define AUX_SERIAL_DMA_Channel_RX DMA_Channel_4
#define AUX_SERIAL_PWR_GPIO GPIOA
#define AUX_SERIAL_PWR_GPIO_PIN GPIO_Pin_15 // PB.00
#if defined(RADIO_TX16S)
#define AUX_SERIAL_PWR_GPIO GPIOA
#define AUX_SERIAL_PWR_GPIO_PIN GPIO_Pin_15 // PA.15
#define TRAINER_BATTERY_COMPARTMENT // allows serial port TTL trainer
#endif
#else

View file

@ -141,29 +141,19 @@ static void LCD_NRSTConfig(void)
GPIO_Init(LCD_GPIO_NRST, &GPIO_InitStructure);
}
// TODO delay function
static void delay3(uint32_t nCount)
{
uint32_t index = 0;
for(index = (1000 * 100 * nCount); index != 0; --index)
{
__asm("nop\n");
}
}
static void lcd_reset(void)
{
#if defined(RADIO_T18) // T18 screen has issues if NRST is ever brought low
NRST_HIGH();
#else
NRST_HIGH();
delay3(1);
delay_ms(1);
NRST_LOW(); // RESET();
delay3(20);
delay_ms(20);
NRST_HIGH();
delay3(30);
delay_ms(30);
#endif
}

View file

@ -43,12 +43,19 @@ enum
GHOST_ID_TOTAL_LATENCY = 0x0007, // Tx-side total latency
GHOST_ID_VTX_FREQ = 0x0008, // Vtx Frequency (in MHz)
GHOST_ID_VTX_POWER = 0x0009, // Vtx Power (in mW)
GHOST_ID_VTX_CHAN = 0x000a, // Vtx Channel
GHOST_ID_VTX_BAND = 0x000b, // Vtx Band
GHOST_ID_VTX_CHAN = 0x000A, // Vtx Channel
GHOST_ID_VTX_BAND = 0x000B, // Vtx Band
GHOST_ID_PACK_VOLTS = 0x000c, // Battery Pack Voltage
GHOST_ID_PACK_AMPS = 0x000d, // Battery Pack Current
GHOST_ID_PACK_MAH = 0x000e, // Battery Pack mAh consumed
GHOST_ID_PACK_VOLTS = 0x000C, // Battery Pack Voltage
GHOST_ID_PACK_AMPS = 0x000D, // Battery Pack Current
GHOST_ID_PACK_MAH = 0x000E, // Battery Pack mAh consumed
GHOST_ID_GPS_LAT = 0x000F, // GPS Latitude
GHOST_ID_GPS_LONG = 0x0010, // GPS Longitude
GHOST_ID_GPS_ALT = 0x0011, // GPS Altitude
GHOST_ID_GPS_HDG = 0x0012, // GPS Heading
GHOST_ID_GPS_GSPD = 0x0013, // GPS Ground Speed
GHOST_ID_GPS_SATS = 0x0014 // GPS Satellite Count
};
const GhostSensor ghostSensors[] = {
@ -70,6 +77,13 @@ const GhostSensor ghostSensors[] = {
{GHOST_ID_PACK_AMPS, ZSTR_CURR, UNIT_AMPS, 2},
{GHOST_ID_PACK_MAH, ZSTR_CAPACITY, UNIT_MAH, 0},
{GHOST_ID_GPS_LAT, ZSTR_GPS, UNIT_GPS_LATITUDE, 0},
{GHOST_ID_GPS_LONG, ZSTR_GPS, UNIT_GPS_LONGITUDE, 0},
{GHOST_ID_GPS_GSPD, ZSTR_GSPD, UNIT_KMH, 1},
{GHOST_ID_GPS_HDG, ZSTR_HDG, UNIT_DEGREE, 3},
{GHOST_ID_GPS_ALT, ZSTR_ALT, UNIT_METERS, 0},
{GHOST_ID_GPS_SATS, ZSTR_SATELLITES, UNIT_RAW, 0},
{0x00, NULL, UNIT_RAW, 0},
};
@ -88,7 +102,11 @@ void processGhostTelemetryValue(uint8_t index, int32_t value)
return;
const GhostSensor * sensor = getGhostSensor(index);
setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, sensor->id, 0, 0, value, sensor->unit, sensor->precision);
uint16_t id = sensor->id;
if (id == GHOST_ID_GPS_LONG) {
id = GHOST_ID_GPS_LAT;
}
setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, id, 0, 0, value, sensor->unit, sensor->precision);
}
void processGhostTelemetryValueString(const GhostSensor * sensor, const char * str)
@ -105,16 +123,19 @@ bool checkGhostTelemetryFrameCRC()
return (crc == telemetryRxBuffer[len + 1]);
}
// hifirst
uint16_t getTelemetryValue_u16(uint8_t index)
{
return (telemetryRxBuffer[index] << 8) | telemetryRxBuffer[index + 1];
}
// lofirst
uint16_t getTelemetryValue_u16le(uint8_t index)
{
return (telemetryRxBuffer[index + 1] << 8) | telemetryRxBuffer[index];
}
// hifirst
uint32_t getTelemetryValue_s32(uint8_t index)
{
uint32_t val = 0;
@ -123,6 +144,15 @@ uint32_t getTelemetryValue_s32(uint8_t index)
return val;
}
// lofirst
uint32_t getTelemetryValue_s32le(uint8_t index)
{
uint32_t val = 0;
for (int i = 0; i < 4; ++i)
val <<= 8, val |= telemetryRxBuffer[index + 3 - i];
return val;
}
void processGhostTelemetryFrame()
{
if (!checkGhostTelemetryFrameCRC()) {
@ -232,7 +262,32 @@ void processGhostTelemetryFrame()
processGhostTelemetryValue(GHOST_ID_PACK_VOLTS, getTelemetryValue_u16le(3));
processGhostTelemetryValue(GHOST_ID_PACK_AMPS, getTelemetryValue_u16le(5));
processGhostTelemetryValue(GHOST_ID_PACK_MAH, getTelemetryValue_u16le(7) * 10);
break;
}
case GHST_DL_GPS_PRIMARY: {
#if defined(BLUETOOTH)
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
}
#endif
processGhostTelemetryValue(GHOST_ID_GPS_LAT, getTelemetryValue_s32le(3) / 10);
processGhostTelemetryValue(GHOST_ID_GPS_LONG, getTelemetryValue_s32le(7) / 10);
processGhostTelemetryValue(GHOST_ID_GPS_ALT, (int16_t) getTelemetryValue_u16le(11));
break;
}
case GHST_DL_GPS_SECONDARY: {
#if defined(BLUETOOTH)
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
}
#endif
processGhostTelemetryValue(GHOST_ID_GPS_HDG, getTelemetryValue_u16le(5) / 10);
// ground speed is passed via GHST as cm/s, converted to km/h for OpenTx
processGhostTelemetryValue(GHOST_ID_GPS_GSPD, (getTelemetryValue_u16le(3) * 36 + 50) / 100);
processGhostTelemetryValue(GHOST_ID_GPS_SATS, telemetryRxBuffer[7]);
break;
}
}
@ -285,6 +340,9 @@ void ghostSetDefault(int index, uint8_t id, uint8_t subId)
const GhostSensor * sensor = getGhostSensor(id);
if (sensor) {
TelemetryUnit unit = sensor->unit;
if (unit == UNIT_GPS_LATITUDE || unit == UNIT_GPS_LONGITUDE) {
unit = UNIT_GPS;
}
uint8_t prec = min<uint8_t>(2, sensor->precision);
telemetrySensor.init(sensor->name, unit, prec);
}

View file

@ -44,6 +44,8 @@
#define GHST_DL_VTX_STAT 0x22
#define GHST_DL_PACK_STAT 0x23
#define GHST_DL_MENU_DESC 0x24
#define GHST_DL_GPS_PRIMARY 0x25
#define GHST_DL_GPS_SECONDARY 0x26
#define GHST_RC_CTR_VAL_12BIT 0x7C0 // 0x3e0 << 1
#define GHST_RC_CTR_VAL_8BIT 0x7C

View file

@ -0,0 +1,161 @@
/*
* Copyright (C) OpenTX
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
struct MLinkSensor
{
const uint16_t id;
const char * name;
const TelemetryUnit unit;
const uint8_t precision;
};
const MLinkSensor mlinkSensors[] = {
{MLINK_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 1},
{MLINK_VOLTAGE, ZSTR_VFAS, UNIT_VOLTS, 1},
{MLINK_CURRENT, ZSTR_CURR, UNIT_AMPS, 1},
{MLINK_VARIO, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 1},
{MLINK_SPEED, ZSTR_SPEED, UNIT_KMH, 1},
{MLINK_RPM, ZSTR_RPM, UNIT_RPMS, 0},
{MLINK_TEMP, ZSTR_TEMP1, UNIT_CELSIUS, 1},
{MLINK_HEADING, ZSTR_HDG, UNIT_DEGREE, 1},
{MLINK_ALT, ZSTR_ALT , UNIT_METERS, 0},
{MLINK_FUEL, ZSTR_FUEL, UNIT_PERCENT, 0},
{MLINK_CAPACITY, ZSTR_CAPACITY, UNIT_MAH, 0},
{MLINK_FLOW, ZSTR_FLOW, UNIT_MILLILITERS, 0},
{MLINK_DISTANCE, ZSTR_DIST, UNIT_KM, 1},
{MLINK_LQI, ZSTR_RSSI, UNIT_RAW, 0},
{MLINK_LOSS, ZSTR_LOSS, UNIT_RAW, 0},
{MLINK_TX_RSSI, ZSTR_TX_RSSI, UNIT_RAW, 0},
{MLINK_TX_LQI, ZSTR_TX_QUALITY, UNIT_RAW, 0},
};
const MLinkSensor * getMLinkSensor(uint16_t id)
{
for (const MLinkSensor * sensor = mlinkSensors; sensor->id; sensor++) {
if (id == sensor->id)
return sensor;
}
return nullptr;
}
void processMLinkPacket(const uint8_t * packet)
{
const uint8_t * data = packet + 2;
// Multi telem
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_TX_RSSI, 0, 0, (packet[0] * 100) / 31, UNIT_RAW, 0);
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_TX_LQI, 0, 0, packet[1], UNIT_RAW, 0);
// M-Link telem
if (data[0] == 0x13) { // Telemetry type RX-9
for (uint8_t i = 1; i < 5; i += 3) { //2 sensors per packet
int32_t val = (int16_t )(data[i + 2] << 8 | data[i + 1]);
val = val >> 1; // remove alarm flag
uint8_t adress = (data[i] & 0xF0) >> 4;
switch (data[i] & 0x0F) {
case MLINK_VOLTAGE:
if ((data[i] & 0xF0) == 0x00){
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_RX_VOLTAGE, 0, adress, val, UNIT_VOLTS, 1);
}
else {
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_VOLTAGE, 0, adress, val, UNIT_VOLTS, 1);
}
break;
case MLINK_CURRENT:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_CURRENT, 0, adress, val, UNIT_AMPS, 1);
break;
case MLINK_VARIO:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_VARIO, 0, adress, val, UNIT_METERS_PER_SECOND, 1);
break;
case MLINK_SPEED:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_SPEED, 0, adress, val, UNIT_KMH, 1);
break;
case MLINK_RPM:
if (val < 0) {
val = -val * 10;
}
else {
val = val * 100;
}
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_RPM, 0, adress, val, UNIT_RPMS, 0);
break;
case MLINK_TEMP:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_TEMP, 0, adress, val, UNIT_CELSIUS, 1);
break;
case MLINK_HEADING:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_HEADING, 0, adress, val, UNIT_DEGREE, 1);
break;
case MLINK_ALT:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_ALT, 0, adress, val, UNIT_METERS, 0);
break;
case MLINK_FUEL:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_FUEL, 0, adress, val, UNIT_PERCENT, 0);
break;
case MLINK_CAPACITY:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_CAPACITY, 0, adress, val, UNIT_MAH, 0);
break;
case MLINK_FLOW:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_FLOW, 0, adress, val, UNIT_MILLILITERS, 0);
break;
case MLINK_DISTANCE:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_DISTANCE, 0, adress, val, UNIT_KM, 1);
break;
case MLINK_LQI:
uint8_t mlinkRssi = data[i + 1] >> 1;
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_LQI, 0, 0, mlinkRssi, UNIT_RAW, 0);
telemetryData.rssi.set(mlinkRssi);
if (mlinkRssi > 0) {
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
break;
}
}
}
else if (packet[2] == 0x03) { // Telemetry type RX-5
uint16_t mlinkRssi = (packet[4] * 100) / 35;
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_LQI, 0, 0, mlinkRssi, UNIT_RAW, 0);
telemetryData.rssi.set(mlinkRssi);
if (mlinkRssi > 0) {
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_LOSS, 0, 0, packet[7], UNIT_RAW, 0);
}
}
void mlinkSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance)
{
TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index];
telemetrySensor.id = id;
telemetrySensor.subId = subId;
telemetrySensor.instance = instance;
const MLinkSensor * sensor = getMLinkSensor(id);
if (sensor) {
TelemetryUnit unit = sensor->unit;
uint8_t prec = min<uint8_t>(2, sensor->precision);
telemetrySensor.init(sensor->name, unit, prec);
if (unit == UNIT_RPMS) {
telemetrySensor.custom.ratio = 1;
telemetrySensor.custom.offset = 1;
}
}
else {
telemetrySensor.init(id);
}
storageDirty(EE_MODEL);
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
enum {
MLINK_VOLTAGE = 1,
MLINK_CURRENT = 2,
MLINK_VARIO = 3,
MLINK_SPEED = 4,
MLINK_RPM = 5,
MLINK_TEMP = 6,
MLINK_HEADING = 7,
MLINK_ALT = 8,
MLINK_FUEL = 9,
MLINK_LQI = 10,
MLINK_CAPACITY = 11,
MLINK_FLOW = 12,
MLINK_DISTANCE = 13,
MLINK_RX_VOLTAGE = 16, // out of range ID for specific RxBt treatment
MLINK_LOSS = 17, // out of range ID for handling number of loss
MLINK_TX_RSSI = 18, // out of range ID for handling Telemetry RSSi reported by multi
MLINK_TX_LQI = 19, // out of range ID for handling Telemetry LQI reported by multi
};
void processMLinkTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount);
void mlinkSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance);
// Used by multi protocol
void processMLinkPacket(const uint8_t *packet);

View file

@ -42,6 +42,7 @@ enum MultiPacketTypes : uint8_t
FlyskyIBusTelemetryAC,
MultiRxChannels,
HottTelemetry,
MLinkTelemetry
};
enum MultiBufferState : uint8_t
@ -360,6 +361,13 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module)
TRACE("[MP] Received HoTT telemetry len %d < 14", len);
break;
case MLinkTelemetry:
if (len > 6)
processMLinkPacket(data);
else
TRACE("[MP] Received M-Link telemetry len %d < 6", len);
break;
case FrSkyHubTelemetry:
if (len >= 4)
frskyDProcessPacket(data);

View file

@ -33,6 +33,7 @@
#include "hitec.h"
#include "hott.h"
#include "multi.h"
#include "mlink.h"
#endif
#if defined(MULTIMODULE) || defined(AFHDS3)
#include "flysky_ibus.h"

View file

@ -559,6 +559,10 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui
case PROTOCOL_TELEMETRY_HOTT:
hottSetDefault(index, id, subId, instance);
break;
case PROTOCOL_TELEMETRY_MLINK:
mlinkSetDefault(index, id, subId, instance);
break;
#endif
#if defined(LUA)

View file

@ -98,6 +98,8 @@ ISTR(INPUTNAMES);
#if defined(MULTIMODULE)
ISTR(MULTI_PROTOCOLS);
ISTR(MULTI_POWER);
ISTR(MULTI_TELEMETRY_MODE);
ISTR(MULTI_WBUS_MODE);
#endif
#if defined(BLUETOOTH)
@ -707,6 +709,7 @@ const char STR_BIND_OK[] = TR_BIND_OK;
const char STR_MULTI_CUSTOM[] = TR_MULTI_CUSTOM;
const char STR_MULTI_RFTUNE[] = TR_MULTI_RFTUNE;
const char STR_MULTI_RFPOWER[] = TR_MULTI_RFPOWER;
const char STR_MULTI_WBUS[] = TR_MULTI_WBUS;
const char STR_MULTI_TELEMETRY[] = TR_MULTI_TELEMETRY;
const char STR_MULTI_VIDFREQ[] = TR_MULTI_VIDFREQ;
const char STR_MULTI_OPTION[] = TR_MULTI_OPTION;

View file

@ -161,6 +161,8 @@ extern const char STR_R9M_PXX2_RF_PROTOCOLS[];
extern const char STR_DSM_PROTOCOLS[];
extern const char STR_MULTI_PROTOCOLS[];
extern const char STR_MULTI_POWER[];
extern const char STR_MULTI_TELEMETRY_MODE[];
extern const char STR_MULTI_WBUS_MODE[];
extern const char STR_SPORT_MODES[];
#if defined(AFHDS3)
@ -403,6 +405,7 @@ extern const char STR_MULTI_OPTION[];
extern const char STR_MULTI_VIDFREQ[];
extern const char STR_MULTI_RFTUNE[];
extern const char STR_MULTI_RFPOWER[];
extern const char STR_MULTI_WBUS[];
extern const char STR_MULTI_TELEMETRY[];
extern const char STR_MULTI_AUTOBIND[];
extern const char STR_DISABLE_CH_MAP[];

View file

@ -260,7 +260,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metr.\0""Imper.", "Metrické""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -639,6 +639,7 @@
#define TR_RECEIVER "Přijímač"
#define TR_MULTI_RFTUNE TR(INDENT "Ladění frek", INDENT "Jemné ladění frek. RF")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetrie"
#define TR_MULTI_VIDFREQ TR(INDENT "Freq. videa", INDENT "Frekvence videa")
#define TR_RFPOWER "Výkon RF"
@ -1380,3 +1381,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -263,7 +263,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\012")
#define TR_VUNITSSYSTEM TR("Metrik""Imper.", "Metrisch\0 ""Imperial\0 ")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -641,6 +641,7 @@
#define TR_RECEIVER "Empfänger"
#define TR_MULTI_RFTUNE TR(INDENT "RF Freq.", INDENT "RF Freq. Feintuning")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR(INDENT "Vid. Freq.", INDENT "Video Frequenz")
#define TR_RFPOWER "RF Power"
@ -1387,3 +1388,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -263,7 +263,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -640,6 +640,7 @@
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@ -1384,3 +1385,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -260,7 +260,7 @@
#define LEN_VUNITSSYSTEM "\010"
#define TR_VUNITSSYSTEM "Métrico\0""Imperial"
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -642,6 +642,7 @@
#define TR_RECEIVER "Receptor"
#define TR_MULTI_RFTUNE TR("Sint.freq.", "RF Freq. sint.fina")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetría"
#define TR_MULTI_VIDFREQ TR("Freq.vídeo", "Frecuencia vídeo")
#define TR_RFPOWER "RF Power"
@ -1383,3 +1384,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -281,7 +281,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -658,6 +658,7 @@
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@ -1391,3 +1392,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -283,7 +283,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\012")
#define TR_VUNITSSYSTEM TR("Métr.\0""Impér.", "Métriques\0""Impériales")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -661,6 +661,7 @@
#define TR_RECEIVER "Récept."
#define TR_MULTI_RFTUNE TR(INDENT "Ajust.fréq", INDENT "Ajustement fréq.")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Télémétrie"
#define TR_MULTI_VIDFREQ TR(INDENT "Fréq. vidéo", INDENT "Fréquence vidéo")
#define TR_RFPOWER TR("Puiss. RF", "Puissance RF")
@ -1408,3 +1409,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -284,7 +284,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\011")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metriche\0""Imperiali")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -462,7 +462,7 @@
#define TR_TTRIM TR("Trim Mot.", INDENT "Trim Motore")
#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch")
#define TR_BEEPCTR TR("Beep al c.", "Beep al centro")
#define TR_USE_GLOBAL_FUNCS "Usa Funz. Globali"
#define TR_USE_GLOBAL_FUNCS TR("Funz. Glob.", "Usa Funz. Globali")
#if defined(PCBSKY9X) && defined(REVX)
#define TR_OUTPUT_TYPE INDENT "Uscita"
#endif
@ -660,6 +660,7 @@
#define TR_RECEIVER "Ricevente"
#define TR_MULTI_RFTUNE TR("Tune RF", "Tune fine Freq. RF")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetria"
#define TR_MULTI_VIDFREQ TR("Freq. video", "Frequenza video")
#define TR_RFPOWER "Potenza RF"
@ -883,7 +884,7 @@
#define TR_MORE_OPTIONS_AVAILABLE "Altre opzioni assenti"
#define TR_NO_MODULE_INFORMATION "Nessuna info del modulo"
#define TR_EXTERNALRF "Modulo esterno"
#define TR_FAILSAFE "Modo failsafe"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Modo failsafe")
#define TR_FAILSAFESET TR(INDENT "FAILSAFE", INDENT "IMPOSTAZIONI FAILSAFE")
#define TR_REG_ID "Reg. ID"
#define TR_OWNER_ID "Owner ID"
@ -934,7 +935,7 @@
#define TR_SPEAKER INDENT "Speaker"
#define TR_BUZZER INDENT "Buzzer"
#define TR_BYTES "Bytes"
#define TR_MODULE_BIND "[Bind]"
#define TR_MODULE_BIND TR("[Bnd]","[Bind]")
#define TR_POWERMETER_ATTN_NEEDED "Attenuatore necessario"
#define TR_PXX2_SELECT_RX "Seleziona RX..."
#define TR_PXX2_DEFAULT "<default>"
@ -947,7 +948,7 @@
#define TR_SHARE "Condividere"
#define TR_BIND "Bind"
#define TR_REGISTER TR("Reg", "Registrare")
#define TR_MODULE_RANGE "[Range]"
#define TR_MODULE_RANGE TR("[Rng]","[Range]")
#define TR_RECEIVER_OPTIONS TR("OPZIONI RX", "OPZIONI RICEVENTE")
#define TR_DEL_BUTTON BUTTON(TR("Canc.", "Cancella"))
#define TR_RESET_BTN "[Reset]"
@ -970,7 +971,7 @@
#define TR_TOPLCDTIMER "Timer LCD Sup."
#define TR_UNIT "Unita"
#define TR_TELEMETRY_NEWSENSOR INDENT "Aggiungi nuovo sensore"
#define TR_CHANNELRANGE INDENT "Numero Canali"
#define TR_CHANNELRANGE TR(INDENT "Num Canali", INDENT "Numero Canali")
#define TR_AFHDS3_RX_FREQ TR("Freq. RX", "Frequenza RX")
#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetria")
#define TR_AFHDS3_ONE_TO_MANY "Multicast"
@ -1401,3 +1402,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -264,7 +264,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Mtrsch""Engels", "Metrisch\0 ""Engels\0 ")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -646,6 +646,7 @@
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@ -1393,3 +1394,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -281,7 +281,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010") /*8 decimal*/
#define TR_VUNITSSYSTEM TR("Metr. ""Imper.", "Metryczn""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -659,6 +659,7 @@
#define TR_RECEIVER INDENT "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@ -1400,3 +1401,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -277,7 +277,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -661,6 +661,7 @@
#define TR_SYNCMENU "Sync [MENU]"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@ -1400,3 +1401,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -278,7 +278,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metri.""Imper.", "Metriska""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@ -659,6 +659,7 @@
#define TR_SYNCMENU "Synk [MENU]"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@ -1400,3 +1401,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"

View file

@ -134,7 +134,13 @@
#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""Futaba\0""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""Height\0""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 ""Kyosho\0""RadLink""ExpLRS\0""Realacc""OMP\0 ""M-Link\0""Wfly 2\0""E016Hv2"
#define LEN_MULTI_POWER "\005"
#define TR_MULTI_POWER "10mW\0""25mW\0""50mW\0""100mW""200mW""300mW""500mW""1W\0 ""2W\0 "
#define TR_MULTI_POWER "1.6mW""2.0mW""2.5mW""3.2mW""4.0mW""5.0mW""6.3mW""7.9mW""10mW\0""13mW\0""16mW\0""20mW\0""25mW\0""32mW\0""40mW\0""50mW\0"
#define LEN_MULTI_WBUS_MODE "\004"
#define TR_MULTI_WBUS_MODE "WBUS""PPM\0"
#define LEN_MULTI_TELEMETRY_MODE "\007"
#define TR_MULTI_TELEMETRY_MODE "Off\0 ""On\0 ""Off+Aux""On+Aux\0"
#define LEN_AFHDS3_PROTOCOLS "\x008"
#define TR_AFHDS3_PROTOCOLS "PWM/IBUS""PWM/SBUS""PPM/IBUS""PPM/SBUS"

View file

@ -41,6 +41,7 @@ for i, (s, f) in enumerate([("volt", "volt0"), ("volts", "volt1"),
("hertz", "hertz0"), ("hertz", "hertz1"),
("milisecond", "ms0"), ("miliseconds", "ms1"),
("microsecond", "us0"), ("microseconds", "us1"),
("kilometer", "km0"), ("kilometers", "km1"),
("hour", "hour0"), ("hours", "hour1"),
("minute", "minute0"), ("minutes", "minute1"),
("second", "second0"), ("seconds", "second1"),

View file

@ -39,6 +39,10 @@ for i, (s, f) in enumerate([("volts", "volt0"),
("millilitres", "ml0"),
("onces", "founce0"),
("millilitre minute", "mlpm0"),
("microsecond", "us0"),
("milisecond", "ms0"),
("hertz", "hertz0"),
("kilometre", "km0"),
("heure", "hour0"),
("minute", "minute0"),
("seconde", "second0"),