1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-13 11:29:51 +03:00

Merge with latest 2.3

This commit is contained in:
Bertrand Songis 2021-01-12 17:16:15 +01:00
commit a02bf3aa0c
No known key found for this signature in database
GPG key ID: F189F79290FEC50F
118 changed files with 7785 additions and 6935 deletions

View file

@ -6,7 +6,7 @@ set(VERSION_REVISION "0")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
set(SDCARD_REVISION "0034")
set(SDCARD_REVISION "0035")
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8)

View file

@ -1,6 +1,7 @@
[Main developers]
Bertrand Songis (bsongis)
André Bernet (kilrah)
JC D. (3djc)
Michael Blandford
Damjan Adamic (projectkk2glider)
Franck Aguerre (jivarofad)
@ -9,6 +10,7 @@ Martin Hotař (mhotar)
Maxim (Max) Paperno (mpaperno)
Arne Schwabe (schwabe)
Daniel Gorbea (dgatf)
Neil Horne (elecpower)
[Translators]
[fr] Sebastien Charpentier (LapinFou)
@ -1942,3 +1944,152 @@ Miklos Turcsin
Edward Skerness
Stefano Perinetti
Toni Marchante
Stuart Olson
Peter Campbell
Keith Wood
Leo Duflou
Michael Florey
Gerhard Weixelbaumer
Peter K Lehotsky
Elisha Jones
Joerg Sattler
paul42
Pascal Heg
Bjorn Sorenssen
Chris Payne
Pascal Afflard
Robert Boboryko
Chris Whitehead
David Bradley
Ian Lever
Phillip Barber
Jan Bronee
N Haasnoot
Rick Smith
Randall Grant
Patrick Degouy
Piotr Zdanowski
David Gardner
TMac FPV
Bernard Thompson
Mark Sutton
Darren J Crane
Michael Keyes
Magnus Borg
David Lorentzen
Antony Smith
Aleksandr Sarkisov
Johannes Kuhne
Kathleen Cilluffo
David Hoffmann
Alan Porter
Arlé Mooldijk
Tenbones
Kim Bitsch Lauridsen
Arthur Costerus
Peter Harvey
John Simpson
Landy de los Santos
Graham Ridley
Schenk Peter
Joseph Rex
Richard Honeywell
Roy Nixon
Andrew Shewan
David Bradley
Alan Micklethwaite
Susan Siegel
Stephen Evans
William Hallman
Franck Michel
László Gajcsi (monthly)
Danny Koch
Robert Martin
Gavin Meerwald
Frédéric Maix
Frank Steinberg
Kevin Berkefeld
Marccos Colon
Kerry Reynolds
Kim Jeppesen
Arthur Peters
Andrew Lowes
Anthony Hallo
Bill Hill
Gerard Falaise
Kevin Raynor
Lorenzo gh
Jan Landeweer
David Bland
Manuel Spoerri
Jeff Jacobs
David Thorne
Maddox Philip
James Jewitt
Justin Digby
John Magnuson (monthly)
Holger Lippert
Hubert Huber
David Blum
Noam Kfir
Mats gårdstad friberg
Jesper Frickmann
Alan Bunker
Emanuel Kircher
Barry Andersen
Gabriel Formanek
Timothy Justiniano
Kelvin Garcia Urbina
Jan Lau
Choon Wei Jonathan Tan
Daniel Navas
Ray Moss
Markus Frielingsdorf
Michael Hirschauer
Jesse Frey
Philipp Koch
Robert Rubio
Dennis G Miller
Leonardo Garcia Osuna
Antonio Carrasco Pastor
Musa Pinar
Jens Moder
Josef de Beer
Chad Mofford
Pim Pouw
Kenth Jonsson
Gordon Westfall
Jean-Michel Saves
Roberto Orsello
Luboš Konvalinka
Lawrence Dorn
Michael Dittmann
Bernd Schmiedel
Raoul Piccioli
Uwe Probst
Glendon Satchell
Trevor Collins
Horst Grashauser
Miguel José Cárdenas Herrera
Mike Jennings
José Bernardo
Carlos Dangle
Gordon Evans
Pablo Peinado Abad
Carl Payne
Adam Sosnowski
Гасак Сергей
SaltCtyRacingFPV
Georg Bernhardt
James Mildenhall
Dave Plummer
Ivan Mokris
Patrick Daniels
Stuart Olson
Cory Znebel
Andrey Yarovoy
Christian Pons
Burt Pickard-Richardson
Michal Mesaros
Conrad Young
Martin Mathes

View file

@ -71,6 +71,7 @@
#define CPN_STR_APP_SETTINGS_FILTER CPN_STR_APP_SETTINGS_FILES % " (*.ini)"
#define CPN_STR_UNKNOWN_ITEM "???"
#define CPN_STR_NONE_ITEM "----"
#define CPN_STR_SW_INDICATOR_UP QCoreApplication::translate("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
#define CPN_STR_SW_INDICATOR_DN QCoreApplication::translate("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.

View file

@ -43,7 +43,7 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs));
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs));
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, CPN_MAX_SENSORS * 3);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, fw->getCapability(Sensors) * 3);
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars));
}
@ -67,10 +67,14 @@ void RawSourceItemModel::addItems(const RawSourceType & type, const int group, c
}
}
void RawSourceItemModel::update() const
void RawSourceItemModel::update()
{
emit dataAboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt()));
emit dataUpdateComplete();
}
@ -86,7 +90,7 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett
// Descending switch direction: NOT (!) switches
addItems(SWITCH_TYPE_ACT, -1);
addItems(SWITCH_TYPE_SENSOR, -CPN_MAX_SENSORS);
addItems(SWITCH_TYPE_SENSOR, -fw->getCapability(Sensors));
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches));
@ -105,7 +109,7 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett
addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
addItems(SWITCH_TYPE_SENSOR, CPN_MAX_SENSORS);
addItems(SWITCH_TYPE_SENSOR, fw->getCapability(Sensors));
addItems(SWITCH_TYPE_ON, 1);
addItems(SWITCH_TYPE_ONE, 1);
addItems(SWITCH_TYPE_ACT, 1);
@ -166,8 +170,95 @@ void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
}
}
void RawSwitchItemModel::update() const
void RawSwitchItemModel::update()
{
emit dataAboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt()));
emit dataUpdateComplete();
}
//
// CurveItemModel
//
CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
const int count = getCurrentFirmware()->getCapability(NumCurves);
for (int i = -count ; i <= count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, ItemIdRole);
int flags;
if (i < 0)
flags = DataGroups::NegativeGroup;
else if (i > 0)
flags = DataGroups::PositiveGroup;
else
flags = DataGroups::NoneGroup;
modelItem->setData(flags, ItemFlagsRole);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CurveItemModel::setDynamicItemData(QStandardItem * item, int index) const
{
item->setText(CurveReference(CurveReference::CURVE_REF_CUSTOM, index).toString(modelData, false));
item->setData(true, IsAvailableRole);
}
void CurveItemModel::update()
{
emit dataAboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt());
emit dataUpdateComplete();
}
//
// CommonItemModels
//
CommonItemModels::CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
QObject(parent)
{
m_rawSourceItemModel = new RawSourceItemModel(generalSettings, modelData, parent);
m_rawSwitchItemModel = new RawSwitchItemModel(generalSettings, modelData, parent);
m_curveItemModel = new CurveItemModel(generalSettings, modelData, parent);
}
CommonItemModels::~CommonItemModels()
{
}
void CommonItemModels::update(const RadioModelObjects radioModelObjects)
{
switch (radioModelObjects) {
case RMO_CHANNELS:
case RMO_INPUTS:
case RMO_TELEMETRY_SENSORS:
case RMO_TIMERS:
m_rawSourceItemModel->update();
break;
case RMO_FLIGHT_MODES:
case RMO_GLOBAL_VARIABLES:
case RMO_LOGICAL_SWITCHES:
m_rawSourceItemModel->update();
m_rawSwitchItemModel->update();
break;
case RMO_CURVES:
m_curveItemModel->update();
break;
case RMO_SCRIPTS:
// no need to refresh
break;
default:
qDebug() << "Unknown RadioModelObject:" << radioModelObjects;
}
}

View file

@ -36,6 +36,13 @@ class AbstractRawItemDataModel: public QStandardItemModel
enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole };
Q_ENUM(DataRoles)
enum DataGroups {
NoneGroup = 0x01,
NegativeGroup = 0x02,
PositiveGroup = 0x04
};
Q_ENUM(DataGroups)
explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
QStandardItemModel(parent),
generalSettings(generalSettings),
@ -43,7 +50,11 @@ class AbstractRawItemDataModel: public QStandardItemModel
{}
public slots:
virtual void update() const = 0;
virtual void update() = 0;
signals:
void dataAboutToBeUpdated();
void dataUpdateComplete();
protected:
const GeneralSettings * generalSettings;
@ -58,7 +69,7 @@ class RawSourceItemModel: public AbstractRawItemDataModel
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() const override;
void update() override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
@ -73,7 +84,7 @@ class RawSwitchItemModel: public AbstractRawItemDataModel
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() const override;
void update() override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
@ -81,4 +92,49 @@ class RawSwitchItemModel: public AbstractRawItemDataModel
};
class CurveItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() override;
protected:
void setDynamicItemData(QStandardItem * item, int index) const;
};
class CommonItemModels: public QObject
{
Q_OBJECT
public:
enum RadioModelObjects {
RMO_CHANNELS,
RMO_CURVES,
RMO_FLIGHT_MODES,
RMO_GLOBAL_VARIABLES,
RMO_INPUTS,
RMO_LOGICAL_SWITCHES,
RMO_SCRIPTS,
RMO_TELEMETRY_SENSORS,
RMO_TIMERS
};
Q_ENUM(RadioModelObjects)
explicit CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
~CommonItemModels();
void update(const RadioModelObjects radioModelObjects);
RawSourceItemModel * rawSourceItemModel() const { return m_rawSourceItemModel; }
RawSwitchItemModel * rawSwitchItemModel() const { return m_rawSwitchItemModel; }
CurveItemModel * curveItemModel() const { return m_curveItemModel; }
private:
RawSourceItemModel *m_rawSourceItemModel;
RawSwitchItemModel *m_rawSwitchItemModel;
CurveItemModel *m_curveItemModel;
};
#endif // RAWITEMDATAMODELS_H

View file

@ -19,7 +19,6 @@
*/
#include "rawitemfilteredmodel.h"
#include "rawitemdatamodels.h"
RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) :
QSortFilterProxyModel(parent),
@ -30,6 +29,12 @@ RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int
setFilterFlags(flags);
setDynamicSortFilter(true);
setSourceModel(sourceModel);
AbstractRawItemDataModel * itemModel = qobject_cast<AbstractRawItemDataModel *>(sourceModel);
if (itemModel) {
connect(itemModel, &AbstractRawItemDataModel::dataAboutToBeUpdated, this, &RawItemFilteredModel::onDataAboutToBeUpdated);
connect(itemModel, &AbstractRawItemDataModel::dataUpdateComplete, this, &RawItemFilteredModel::onDataUpdateComplete);
}
}
void RawItemFilteredModel::setFilterFlags(int flags)
@ -56,19 +61,17 @@ bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & s
void RawItemFilteredModel::update() const
{
AbstractRawItemDataModel * model = qobject_cast<AbstractRawItemDataModel *>(sourceModel());
if (model)
model->update();
AbstractRawItemDataModel * itemModel = qobject_cast<AbstractRawItemDataModel *>(sourceModel());
if (itemModel)
itemModel->update();
}
RawSourceFilterItemModel::RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent) :
RawItemFilteredModel(new RawSourceItemModel(generalSettings, modelData, parent), flags, parent)
void RawItemFilteredModel::onDataAboutToBeUpdated()
{
emit dataAboutToBeUpdated();
}
RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent) :
RawItemFilteredModel(new RawSwitchItemModel(generalSettings, modelData, parent), context, parent)
void RawItemFilteredModel::onDataUpdateComplete()
{
emit dataUpdateComplete();
}

View file

@ -21,54 +21,43 @@
#ifndef RAWITEMFILTEREDMODEL_H
#define RAWITEMFILTEREDMODEL_H
#include "rawitemdatamodels.h"
#include <QSortFilterProxyModel>
class GeneralSettings;
class ModelData;
class RawSourceItemModel;
class RawSwitchItemModel;
class RawItemFilteredModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
enum DataFilters {
AllFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup | AbstractRawItemDataModel::PositiveGroup,
AllExcludeNoneFilter = AllFilter &~ AbstractRawItemDataModel::NoneGroup,
NegativeFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup,
NegativeExcludeNoneFilter = AbstractRawItemDataModel::NegativeGroup,
PositiveFilter = AbstractRawItemDataModel::PositiveGroup | AbstractRawItemDataModel::NoneGroup,
PositiveExcludeNoneFilter = AbstractRawItemDataModel::PositiveGroup
};
Q_ENUM(DataFilters)
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr);
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {}
public slots:
void setFilterFlags(int flags);
void update() const;
void onDataAboutToBeUpdated();
void onDataUpdateComplete();
signals:
void dataAboutToBeUpdated();
void dataUpdateComplete();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
int filterFlags;
};
// The specialized "convenience" types below can go away once centralalized RawSource/RawSwitch item models are established.
// These proxy classes will automatically create a source model of the corresponding type.
class RawSwitchFilterItemModel: public RawItemFilteredModel
{
Q_OBJECT
public:
using RawItemFilteredModel::RawItemFilteredModel;
explicit RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent = nullptr);
};
class RawSourceFilterItemModel: public RawItemFilteredModel
{
Q_OBJECT
public:
using RawItemFilteredModel::RawItemFilteredModel;
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent = nullptr);
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
RawSourceFilterItemModel(generalSettings, modelData, 0, parent) {}
};
#endif // RAWITEMFILTEREDMODEL_H

View file

@ -32,8 +32,14 @@ list(APPEND firmwares_HDRS
moduledata.h
)
set(firmwares_QT
curvereference.h
)
qt5_wrap_cpp(firmwares_SRCS ${firmwares_QT})
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
target_link_libraries(firmwares ${CPN_COMMON_LIB} Qt5::Core Qt5::Xml Qt5::Widgets)
target_link_libraries(firmwares ${CPN_COMMON_LIB} datamodels Qt5::Core Qt5::Xml Qt5::Widgets)
target_include_directories(firmwares
PRIVATE
${CMAKE_SOURCE_DIR}

View file

@ -191,7 +191,20 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
else if (IS_TARANIS_X7(board)) {
else if (board == BOARD_TARANIS_X7_ACCESS) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_3POS, "SC"},
{SWITCH_3POS, "SD"},
{SWITCH_2POS, "SF"},
{SWITCH_TOGGLE, "SH"},
{SWITCH_2POS, "SI"}
};
if (index < DIM(switches))
return switches[index];
}
else if (board == BOARD_TARANIS_X7) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@ -350,7 +363,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 5;
else if (board == Board::BOARD_TARANIS_X9LITES)
return 7;
else if (IS_TARANIS_X7(board))
else if (board == BOARD_TARANIS_X7_ACCESS)
return 7;
else if (board == BOARD_TARANIS_X7)
return 8;
else if (IS_FAMILY_T12(board))
return 8;

View file

@ -19,45 +19,293 @@
*/
#include "curvereference.h"
#include "adjustmentreference.h"
#include "helpers.h"
#include "modeldata.h"
#include "rawitemfilteredmodel.h"
#include "helpers.h" // for Helpers::getAdjustmentString()
#include "radiodata.h" // for ModelData
QString CurveReference::toString(const ModelData * model, bool verbose) const
const QString CurveReference::toString(const ModelData * model, bool verbose) const
{
if (value == 0) {
return "----";
}
if (value == 0)
return CPN_STR_NONE_ITEM;
QString ret;
unsigned idx = abs(value) - 1;
switch(type) {
case CURVE_REF_DIFF:
ret = tr("Diff(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_EXPO:
ret = tr("Expo(%1)").arg(Helpers::getAdjustmentString(value, model));
ret = AdjustmentReference(value).toString(model);
break;
case CURVE_REF_FUNC:
ret = QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3);
if (verbose)
ret = tr("Function(%1)").arg(ret);
ret = functionToString(value);
break;
default:
case CURVE_REF_CUSTOM:
if (model)
ret = model->curves[idx].nameToString(idx);
else
ret = CurveData().nameToString(idx);
if (verbose)
ret = tr("Curve(%1)").arg(ret);
if (value < 0)
ret.prepend(CPN_STR_SW_INDICATOR_REV);
break;
default:
return CPN_STR_UNKNOWN_ITEM;
}
if (verbose)
ret = tr(qPrintable(QString(typeToString(type) + "(%1)").arg(ret)));
return ret;
}
const bool CurveReference::isValueNumber() const
{
return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE;
}
// static
int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar)
{
if (isGVar && (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO))
return AdjustmentReference(AdjustmentReference::ADJUST_REF_GVAR, 1).toValue();
else if (type == CURVE_REF_FUNC)
return 1;
else
return 0;
}
// static
QString CurveReference::typeToString(const CurveRefType type)
{
const QStringList strl = { "Diff", "Expo" , "Func", "Curve" };
int idx = (int)type;
if (idx < 0 || idx >= strl.count())
return CPN_STR_UNKNOWN_ITEM;
return strl.at(idx);
}
constexpr int MAX_CURVE_REF_FUNC { 6 };
// static
QString CurveReference::functionToString(const int value)
{
const QStringList strl = { "x>0", "x<0", "|x|", "f>0", "f<0", "|f|" };
int idx = value - 1;
if (idx < 0 || idx >= strl.count())
return CPN_STR_UNKNOWN_ITEM;
return strl.at(idx);
}
/*
* CurveReferenceUIManager
*/
constexpr int CURVE_REF_UI_HIDE_DIFF { 0x01 };
constexpr int CURVE_REF_UI_HIDE_EXPO { 0x02 };
constexpr int CURVE_REF_UI_HIDE_NEGATIVE_CURVES { 0x04 };
// static
bool CurveReferenceUIManager::firsttime { true };
int CurveReferenceUIManager::flags { 0 };
bool CurveReferenceUIManager::hasCapabilityGvars { false };
int CurveReferenceUIManager::numCurves { 0 };
RawItemFilteredModel * CurveReferenceUIManager::curveItemModel { nullptr };
QStandardItemModel * CurveReferenceUIManager::tempModel { nullptr };
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveValueCB, CurveReference & curve, const ModelData & model,
RawItemFilteredModel * curveItemModel, QObject * parent) :
QObject(parent),
curveTypeCB(nullptr),
curveGVarCB(nullptr),
curveValueSB(nullptr),
curveValueCB(curveValueCB),
curve(curve),
model(model),
lock(false)
{
init(curveItemModel);
}
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB,
QComboBox * curveValueCB, CurveReference & curve, const ModelData & model,
RawItemFilteredModel * curveItemModel, QObject * parent) :
QObject(parent),
curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB),
curveValueSB(curveValueSB),
curveValueCB(curveValueCB),
curve(curve),
model(model),
lock(false)
{
init(curveItemModel);
}
CurveReferenceUIManager::~CurveReferenceUIManager()
{
delete tempModel;
}
void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel)
{
tempModel = new QStandardItemModel();
if (firsttime) {
firsttime = false;
Firmware * fw = getCurrentFirmware();
hasCapabilityGvars = fw->getCapability(Gvars);
numCurves = fw->getCapability(NumCurves);
curveItemModel = curveModel;
if (!fw->getCapability(HasInputDiff))
flags |= (CURVE_REF_UI_HIDE_DIFF | CURVE_REF_UI_HIDE_NEGATIVE_CURVES);
if (!fw->getCapability(HasMixerExpo))
flags |= CURVE_REF_UI_HIDE_EXPO;
}
if (curveTypeCB) {
populateTypeCB(curveTypeCB, curve);
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
}
if (curveGVarCB)
connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
if (curveValueSB) {
curveValueSB->setMinimum(-100);
curveValueSB->setMaximum(100);
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged()));
}
curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents);
curveValueCB->setMaxVisibleItems(10);
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged()));
update();
}
#define CURVE_REF_UI_GVAR_SHOW (1<<0)
#define CURVE_REF_UI_VALUE_SHOW (1<<1)
#define CURVE_REF_UI_REF_SHOW (1<<2)
void CurveReferenceUIManager::update()
{
lock = true;
int widgetsMask = 0;
if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) {
if (hasCapabilityGvars)
widgetsMask |= CURVE_REF_UI_GVAR_SHOW;
if (curve.isValueNumber()) {
curveGVarCB->setChecked(false);
curveValueSB->setValue(curve.value);
widgetsMask |= CURVE_REF_UI_VALUE_SHOW;
}
else {
curveGVarCB->setChecked(true);
widgetsMask |= CURVE_REF_UI_REF_SHOW;
}
}
else {
widgetsMask |= CURVE_REF_UI_REF_SHOW;
}
if(curveTypeCB) {
curveTypeCB->setCurrentIndex(curveTypeCB->findData(curve.type));
curveTypeCB->show();
}
if(curveGVarCB)
curveGVarCB->setVisible(widgetsMask & CURVE_REF_UI_GVAR_SHOW);
if(curveValueSB)
curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW);
if(curveValueCB) {
if (curve.isValueReference())
populateValueCB(curveValueCB, curve, &model);
curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW);
}
lock = false;
}
void CurveReferenceUIManager::gvarCBChanged(int state)
{
if (!lock) {
curve.value = CurveReference::getDefaultValue(curve.type, state);
update();
}
}
void CurveReferenceUIManager::typeChanged(int value)
{
if (!lock) {
CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
curve = CurveReference(type, CurveReference::getDefaultValue(type));
update();
}
}
void CurveReferenceUIManager::valueSBChanged()
{
if (!lock) {
curve.value = curveValueSB->value();
update();
}
}
void CurveReferenceUIManager::valueCBChanged()
{
if (!lock) {
curve.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
update();
}
}
// static
void CurveReferenceUIManager::populateTypeCB(QComboBox * cb, const CurveReference & curveRef)
{
if (cb) {
cb->clear();
for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) {
if ((curveRef.type == CurveReference::CURVE_REF_DIFF && !(flags & CURVE_REF_UI_HIDE_DIFF)) ||
(curveRef.type == CurveReference::CURVE_REF_EXPO && !(flags & CURVE_REF_UI_HIDE_EXPO)) ||
(curveRef.type != CurveReference::CURVE_REF_DIFF && curveRef.type != CurveReference::CURVE_REF_EXPO))
cb->addItem(CurveReference::typeToString((CurveReference::CurveRefType)i), i);
}
cb->setCurrentIndex(cb->findData((int)curveRef.type));
}
}
// static
void CurveReferenceUIManager::populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model)
{
if (cb) {
cb->setModel(tempModel); // do not want to clear/alter the shared curves model and set to nullptr is invalid
switch (curveRef.type) {
case CurveReference::CURVE_REF_DIFF:
case CurveReference::CURVE_REF_EXPO:
cb->clear();
Helpers::populateGVCB(*cb, curveRef.value, *model);
break;
case CurveReference::CURVE_REF_FUNC:
cb->clear();
for (int i = 1; i <= MAX_CURVE_REF_FUNC; i++) {
cb->addItem(CurveReference::functionToString(i), i);
}
break;
case CurveReference::CURVE_REF_CUSTOM:
cb->setModel(curveItemModel);
break;
default:
break;
}
cb->setCurrentIndex(cb->findData(curveRef.value));
}
}

View file

@ -22,35 +22,101 @@
#define CURVEREFERENCE_H
#include <QtCore>
#include <QComboBox>
#include <QCheckBox>
#include <QSpinBox>
#include <QStandardItemModel>
class ModelData;
class RawItemFilteredModel;
class CurveReference {
Q_DECLARE_TR_FUNCTIONS(CurveReference)
public:
enum CurveRefType {
CURVE_REF_DIFF,
CURVE_REF_EXPO,
CURVE_REF_FUNC,
CURVE_REF_CUSTOM
CURVE_REF_CUSTOM,
MAX_CURVE_REF_TYPE = CURVE_REF_CUSTOM
};
enum CurveRefGroups {
NoneGroup = 0x001,
NegativeGroup = 0x002,
PositiveGroup = 0x004,
AllCurveRefGroups = NoneGroup | NegativeGroup | PositiveGroup,
PositiveCurveRefGroups = AllCurveRefGroups &~ NegativeGroup
};
CurveReference() { clear(); }
CurveReference(CurveRefType type, int value):
type(type),
value(value)
{
}
CurveReference(CurveRefType type, int value) : type(type), value(value) { ; }
void clear() { memset(this, 0, sizeof(CurveReference)); }
const bool isEmpty() const { return type == CURVE_REF_DIFF && value == 0; }
const bool isSet() const { return !isEmpty(); }
const bool isValueNumber() const;
const bool isValueReference() const { return !isValueNumber(); }
const QString toString(const ModelData * model = nullptr, bool verbose = true) const;
CurveRefType type;
int value;
QString toString(const ModelData * model = NULL, bool verbose = true) const;
bool isSet() const { return type != CURVE_REF_DIFF || value != 0; }
bool operator == ( const CurveReference & other) const {
return (this->type == other.type) && (this->value == other.value);
}
bool operator != ( const CurveReference & other) const {
return (this->type != other.type) || (this->value != other.value);
}
static int getDefaultValue(const CurveRefType type, const bool isGVar = false);
static QString typeToString(const CurveRefType type);
static QString functionToString(const int value);
};
class CurveReferenceUIManager : public QObject {
Q_OBJECT
public:
CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model,
RawItemFilteredModel * curveItemModel, QObject * parent = nullptr);
CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB,
CurveReference & curve, const ModelData & model, RawItemFilteredModel * curveItemModel, QObject * parent = nullptr);
virtual ~CurveReferenceUIManager();
void init(RawItemFilteredModel * curveModel);
void update();
protected slots:
void gvarCBChanged(int);
void typeChanged(int);
void valueSBChanged();
void valueCBChanged();
protected:
QComboBox *curveTypeCB;
QCheckBox *curveGVarCB;
QSpinBox *curveValueSB;
QComboBox *curveValueCB;
CurveReference & curve;
const ModelData & model;
bool lock;
static bool firsttime;
static int flags;
static bool hasCapabilityGvars;
static int numCurves;
static RawItemFilteredModel * curveItemModel;
static QStandardItemModel * tempModel;
static void populateTypeCB(QComboBox * cb, const CurveReference & curveRef);
static void populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model = nullptr);
};
#endif // CURVEREFERENCE_H

View file

@ -91,10 +91,8 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
return tr("Background Music Pause");
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast)
return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model));
else if (func == FuncSetFailsafeInternalModule)
return tr("SetFailsafe Int. Module");
else if (func == FuncSetFailsafeExternalModule)
return tr("SetFailsafe Ext. Module");
else if (func == FuncSetFailsafe)
return tr("Set Failsafe");
else if (func == FuncRangeCheckInternalModule)
return tr("RangeCheck Int. Module");
else if (func == FuncRangeCheckExternalModule)
@ -126,20 +124,15 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox
b->addItem(tr("REa"), val++);
b->addItem(tr("REb"), val++);
}
if ((int)value < b->count()) {
b->setCurrentIndex(value);
}
if (model) {
for (unsigned i=0; i<CPN_MAX_SENSORS; ++i) {
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);
if (value == val+i) {
b->setCurrentIndex(b->count()-1);
}
}
}
}
b->setCurrentIndex(b->findData(value));
}
void CustomFunctionData::populatePlaySoundParams(QStringList & qs)

View file

@ -62,8 +62,7 @@ enum AssignFunc {
FuncBackgroundMusicPause,
FuncAdjustGV1,
FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1,
FuncSetFailsafeInternalModule,
FuncSetFailsafeExternalModule,
FuncSetFailsafe,
FuncRangeCheckInternalModule,
FuncRangeCheckExternalModule,
FuncBindInternalModule,

View file

@ -723,11 +723,15 @@ int ModelData::updateReference()
updateAssignFunc(cfd);
if (!cfd->isEmpty()) {
updateSwitchRef(cfd->swtch);
if (cfd->func == FuncVolume || cfd->func == FuncBacklight || cfd->func == FuncPlayValue || (cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) {
if (cfd->func == FuncVolume || cfd->func == FuncBacklight || cfd->func == FuncPlayValue ||
(cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) {
updateSourceIntRef(cfd->param);
if (cfd->param == 0)
cfd->clear();
}
else if (cfd->func == FuncReset) {
updateResetParam(cfd);
}
}
}
}
@ -847,7 +851,7 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c
newRef.clear();
else {
newRef.type = (T)defType;
newRef.index = defIndex + idxAdj;
newRef.index = defIndex;
}
break;
case REF_UPD_ACT_SHIFT:
@ -904,7 +908,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c
newRef.clear();
else {
newRef.type = (T)defType;
newRef.value = defValue + idxAdj;
newRef.value = defValue;
}
break;
case REF_UPD_ACT_SHIFT:
@ -972,7 +976,7 @@ void ModelData::updateAssignFunc(CustomFunctionData * cfd)
{
const int invalidateRef = -1;
int newRef = (int)cfd->func;
int idxAdj;
int idxAdj = 0;
switch (updRefInfo.type)
{
@ -989,7 +993,7 @@ void ModelData::updateAssignFunc(CustomFunctionData * cfd)
case REF_UPD_TYPE_TIMER:
if (cfd->func < FuncSetTimer1 || cfd->func > FuncSetTimer3) // TODO refactor to FuncSetTimerLast
return;
idxAdj = FuncSetTimer1 - 2; // reverse earlier offset requiured for rawsource
idxAdj = FuncSetTimer1 - 2; // reverse earlier offset required for rawsource
break;
default:
return;
@ -1374,3 +1378,64 @@ void ModelData::sortMixes()
memcpy(&mixData[0], &sortedMixData[0], CPN_MAX_MIXERS * sizeof(MixData));
}
void ModelData::updateResetParam(CustomFunctionData * cfd)
{
if (cfd->func != FuncReset)
return;
const int invalidateRef = -1;
int newRef = cfd->param;
int idxAdj = 0;
Firmware *firmware = getCurrentFirmware();
switch (updRefInfo.type)
{
case REF_UPD_TYPE_SENSOR:
idxAdj = 5/*3 Timers + Flight + Telemetery*/ + firmware->getCapability(RotaryEncoders);
if (cfd->param < idxAdj || cfd->param > (idxAdj + firmware->getCapability(Sensors)))
return;
break;
default:
return;
}
switch (updRefInfo.action)
{
case REF_UPD_ACT_CLEAR:
if (newRef != (updRefInfo.index1 + idxAdj))
return;
newRef = invalidateRef;
break;
case REF_UPD_ACT_SHIFT:
if (newRef < (updRefInfo.index1 + idxAdj))
return;
newRef += updRefInfo.shift;
if (newRef < (updRefInfo.index1 + idxAdj) || newRef > (updRefInfo.maxindex + idxAdj))
newRef = invalidateRef;
break;
case REF_UPD_ACT_SWAP:
if (newRef == updRefInfo.index1 + idxAdj)
newRef = updRefInfo.index2 + idxAdj;
else if (newRef == updRefInfo.index2 + idxAdj)
newRef = updRefInfo.index1 + idxAdj;
break;
default:
qDebug() << "Error - unhandled action:" << updRefInfo.action;
return;
}
if (newRef == invalidateRef) {
cfd->clear();
//qDebug() << "Function cleared";
updRefInfo.updcnt++;
}
else if (cfd->param != newRef) {
//qDebug() << "Updated reference:" << cfd->param << " -> " << newRef;
cfd->param = newRef;
updRefInfo.updcnt++;
}
}

View file

@ -338,6 +338,7 @@ class ModelData {
value = swtch.toValue();
}
void sortMixes();
void updateResetParam(CustomFunctionData * cfd);
};
#endif // MODELDATA_H

View file

@ -84,7 +84,7 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_MJXQ,
MODULE_SUBTYPE_MULTI_SHENQI,
MODULE_SUBTYPE_MULTI_FY326,
MODULE_SUBTYPE_MULTI_SFHSS,
MODULE_SUBTYPE_MULTI_FUTABA,
MODULE_SUBTYPE_MULTI_J6PRO,
MODULE_SUBTYPE_MULTI_FQ777,
MODULE_SUBTYPE_MULTI_ASSAN,
@ -115,7 +115,7 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_REDPINE,
MODULE_SUBTYPE_MULTI_POTENSIC,
MODULE_SUBTYPE_MULTI_ZSX,
MODULE_SUBTYPE_MULTI_FLYZONE,
MODULE_SUBTYPE_MULTI_HEIGHT,
MODULE_SUBTYPE_MULTI_SCANNER,
MODULE_SUBTYPE_MULTI_FRSKYX_RX,
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
@ -135,7 +135,15 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_DSM_RX,
MODULE_SUBTYPE_MULTI_JJRC345,
MODULE_SUBTYPE_MULTI_Q90C,
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_Q90C
MODULE_SUBTYPE_MULTI_KYOSHO,
MODULE_SUBTYPE_MULTI_RLINK,
MODULE_SUBTYPE_MULTI_ELRS,
MODULE_SUBTYPE_MULTI_REALACC,
MODULE_SUBTYPE_MULTI_OMP,
MODULE_SUBTYPE_MULTI_MLINK,
MODULE_SUBTYPE_MULTI_WFLY2,
MODULE_SUBTYPE_MULTI_E016HV2,
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_E016HV2
};
enum TrainerProtocol {

View file

@ -55,8 +55,9 @@ static const QStringList STR_SUBTYPE_ESky {"Standard", "ET4"};
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH", "Phoenix"};
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
static const QStringList STR_SUBTYPE_FUTABA {"SFHSS"};
static const QStringList STR_SUBTYPE_HONTAI {"Standard", "JJRC X1", "X5C1 Clone", "FQ777_951"};
static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "PWM and SBUS", "PPM and SBUS"};
static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "PWM and SBUS", "PPM and SBUS", "PWM and IBUS16", "PPM and IBUS16"};
static const QStringList STR_SUBTYPE_Q2X2 {"Q222", "Q242", "Q282"};
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
static const QStringList STR_SUBTYPE_Q303 {"Standard", "CX35", "CX10D", "CX10WD"};
@ -65,7 +66,7 @@ static const QStringList STR_SUBTYPE_ESKY150 {"4 Channel", "7 Channel"};
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
static const QStringList STR_SUBTYPE_CORONA {"Corona V1", "Corona V2", "Flydream V3"};
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
static const QStringList STR_SUBTYPE_WFLY {"WFR0xS"};
static const QStringList STR_SUBTYPE_WFLY {"WFR0x"};
static const QStringList STR_SUBTYPE_BUGS_MINI {"Standard", "Bugs 3H"};
static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"};
static const QStringList STR_SUBTYPE_E01X {"E012", "E015", "E016H"};
@ -75,18 +76,24 @@ static const QStringList STR_SUBTYPE_V761 {"3 Channel", "4 Channel"};
static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"};
static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"};
static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"};
static const QStringList STR_SUBTYPE_FLYZONE {"FZ-410 TX"};
static const QStringList STR_SUBTYPE_HEIGHT {"5 Channel", "8 Channel"};
static const QStringList STR_SUBTYPE_FRSKYX_RX {"RX", "Clone TX"};
static const QStringList STR_SUBTYPE_HOTT {"Sync", "No_Sync"};
static const QStringList STR_SUBTYPE_FX816 {"P38"};
static const QStringList STR_SUBTYPE_PELIKAN {"Pro", "Lite"};
static const QStringList STR_SUBTYPE_XK {"X450", "X420"};
static const QStringList STR_SUBTYPE_XN297DUMP {"250K", "1M", "2M", "AUTO", "NRF"};
static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "D16 Cloned"};
static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel"};
static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "Cloned", "Cloned 8ch"};
static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel", "FCC", "---", "FCC 8-Channel"};
static const QStringList STR_SUBTYPE_PROPEL {"74-Z"};
static const QStringList STR_SUBTYPE_FRSKYL {"LR12", "LR12 6-Channel"};
static const QStringList STR_SUBTYPE_ESKY150V2 {"150 V2"};
static const QStringList STR_SUBTYPE_JJRC345 {"Standard", "SkyTumbler"};
static const QStringList STR_SUBTYPE_KYOSHO {"FHSS", "Hype"};
static const QStringList STR_SUBTYPE_RLINK {"Surface", "Air", "DumboRC"};
static const QStringList STR_SUBTYPE_ELRS {"Not Available WIP"};
static const QStringList STR_SUBTYPE_REALACC {"R11"};
static const QStringList STR_SUBTYPE_WFLY2 {"RF20x"};
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
@ -112,11 +119,11 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FUTABA, 0, true, STR_SUBTYPE_FUTABA, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_J6PRO, 0, false, NO_SUBTYPE, nullptr},
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 5, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MODULE_SUBTYPE_MULTI_Q2X2, 2, false, STR_SUBTYPE_Q2X2, nullptr},
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, STR_SUBTYPE_WK2x01, nullptr},
{MODULE_SUBTYPE_MULTI_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
@ -136,20 +143,28 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr},
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr},
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr},
{MODULE_SUBTYPE_MULTI_HEIGHT, 1, false, STR_SUBTYPE_HEIGHT, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HOTT, 1, true, STR_SUBTYPE_HOTT, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FX816, 0, false, STR_SUBTYPE_FX816, nullptr},
{MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, STR_SUBTYPE_PELIKAN, nullptr},
{MODULE_SUBTYPE_MULTI_XK, 1, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, STR_SUBTYPE_XN297DUMP, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX2, 5, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 6, true, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYL, 1, false, STR_SUBTYPE_FRSKYL, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_SKYARTEC, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_ESKY150V2, 0, false, STR_SUBTYPE_ESKY150V2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_JJRC345, 1, false, STR_SUBTYPE_JJRC345, nullptr},
{MODULE_SUBTYPE_MULTI_Q90C, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_KYOSHO, 1, false, STR_SUBTYPE_KYOSHO, nullptr},
{MODULE_SUBTYPE_MULTI_RLINK, 2, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_ELRS, 0, false, STR_SUBTYPE_ELRS, nullptr},
{MODULE_SUBTYPE_MULTI_REALACC, 0, false, STR_SUBTYPE_REALACC, nullptr},
{MODULE_SUBTYPE_MULTI_OMP, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_WFLY2, 0, false, STR_SUBTYPE_WFLY2, STR_MULTI_OPTION},
{MODULE_SUBTYPE_MULTI_E016HV2, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION},
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
@ -189,12 +204,13 @@ QString Multiprotocols::protocolToString(int protocol, bool custom)
{
static const QStringList strings({
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "Futaba", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
"FlySky AFHDS2A", "Q2x2", "WK2x01", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761",
"KFPlan KF606", "Redpine", "Potensic", "ZSX", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816",
"KFPlan KF606", "Redpine", "Potensic", "ZSX", "Height", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816",
"Bayang RX", "Pelikan", "Tiger", "XK", "XN297 Dump", "FrSky X 2.1", "FrSky R9", "Propel", "FrSky L", "Skyartec",
"ESky 150v2", "DSM RX", "JJRC345", "Q90C"
"ESky 150v2", "DSM RX", "JJRC345", "Q90C", "Kyosho", "RadioLink", "ExpressLRS", "Realacc", "OMP", "M-Link", "Wfly 2",
"E016H v2"
});
return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);

View file

@ -48,6 +48,9 @@ inline int MAX_SWITCHES(Board::Type board, int version)
if (IS_FAMILY_T12(board))
return 8;
if (IS_TARANIS_X7(board))
return 8;
return Boards::getCapability(board, Board::Switches);
}
@ -1406,8 +1409,7 @@ class CustomFunctionsConversionTable: public ConversionTable {
addConversion(FuncAdjustGV1+i, val);
val++;
addConversion(FuncVolume, val++);
addConversion(FuncSetFailsafeInternalModule, val);
addConversion(FuncSetFailsafeExternalModule, val++);
addConversion(FuncSetFailsafe, val++);
addConversion(FuncRangeCheckInternalModule, val);
addConversion(FuncRangeCheckExternalModule, val++);
addConversion(FuncBindInternalModule, val);
@ -1520,9 +1522,6 @@ class ArmCustomFunctionField: public TransformedField {
*((uint16_t *)_param) = fn.param;
*((uint8_t *)(_param+3)) = fn.func - FuncSetTimer1;
}
else if (fn.func >= FuncSetFailsafeInternalModule && fn.func <= FuncSetFailsafeExternalModule) {
*((uint16_t *)_param) = fn.func - FuncSetFailsafeInternalModule;
}
else if (fn.func >= FuncRangeCheckInternalModule && fn.func <= FuncRangeCheckExternalModule) {
*((uint16_t *)_param) = fn.func - FuncRangeCheckInternalModule;
}

View file

@ -59,7 +59,7 @@ QString RawSwitch::toString(Board::Type board, const GeneralSettings * const gen
tr("THs"), tr("TH%"), tr("THt")
};
const QStringList directionIndicators = QStringList()
static const QStringList directionIndicators = QStringList()
<< CPN_STR_SW_INDICATOR_UP
<< CPN_STR_SW_INDICATOR_NEUT
<< CPN_STR_SW_INDICATOR_DN;

View file

@ -28,4 +28,4 @@ qt5_wrap_ui(generaledit_SRCS ${generaledit_UIS})
qt5_wrap_cpp(generaledit_SRCS ${generaledit_HDRS})
add_library(generaledit ${generaledit_SRCS})
target_link_libraries(generaledit PRIVATE ${CPN_COMMON_LIB} Qt5::Multimedia)
target_link_libraries(generaledit PRIVATE datamodels ${CPN_COMMON_LIB} Qt5::Multimedia)

View file

@ -28,6 +28,7 @@
#include "hardware.h"
#include "../modeledit/customfunctions.h"
#include "verticalscrollarea.h"
#include "rawitemdatamodels.h"
GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) :
QDialog(parent),
@ -55,8 +56,10 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
}
}
commonItemModels = new CommonItemModels(&generalSettings, nullptr, this);
addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup"));
addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions"));
addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, commonItemModels), tr("Global Functions"));
addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer"));
addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware"));
addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration"));

View file

@ -25,6 +25,8 @@
#include "eeprominterface.h"
#include "genericpanel.h"
class CommonItemModels;
namespace Ui {
class GeneralEdit;
}
@ -71,7 +73,7 @@ class GeneralEdit : public QDialog
QVector<GenericPanel *> panels;
void addTab(GenericPanel *panel, QString text);
void closeEvent(QCloseEvent *event);
CommonItemModels *commonItemModels;
};
#endif // _GENERALEDIT_H_

View file

@ -210,170 +210,6 @@ void GVarGroup::setWeight(int val)
lock = false;
}
/*
* CurveGroup
*/
CurveGroup::CurveGroup(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QComboBox * curveValueCB, QSpinBox * curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags):
QObject(),
curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB),
curveValueCB(curveValueCB),
curveValueSB(curveValueSB),
curve(curve),
model(model),
flags(flags),
lock(false),
lastType(-1)
{
if (!(flags & HIDE_DIFF)) curveTypeCB->addItem(tr("Diff"), 0);
if (!(flags & HIDE_EXPO)) curveTypeCB->addItem(tr("Expo"), 1);
curveTypeCB->addItem(tr("Func"), 2);
curveTypeCB->addItem(tr("Curve"), 3);
curveValueCB->setMaxVisibleItems(10);
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
update();
}
void CurveGroup::update()
{
lock = true;
int found = curveTypeCB->findData(curve.type);
if (found < 0) found = 0;
curveTypeCB->setCurrentIndex(found);
if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) {
curveGVarCB->setVisible(getCurrentFirmware()->getCapability(Gvars));
if (curve.value > 100 || curve.value < -100) {
curveGVarCB->setChecked(true);
if (lastType != CurveReference::CURVE_REF_DIFF && lastType != CurveReference::CURVE_REF_EXPO) {
lastType = curve.type;
Helpers::populateGVCB(*curveValueCB, curve.value, model);
}
curveValueCB->show();
curveValueSB->hide();
}
else {
curveGVarCB->setChecked(false);
curveValueSB->setMinimum(-100);
curveValueSB->setMaximum(100);
curveValueSB->setValue(curve.value);
curveValueSB->show();
curveValueCB->hide();
}
}
else {
curveGVarCB->hide();
curveValueSB->hide();
curveValueCB->show();
switch (curve.type) {
case CurveReference::CURVE_REF_FUNC:
if (lastType != curve.type) {
lastType = curve.type;
curveValueCB->clear();
for (int i=0; i<=6/*TODO constant*/; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_FUNC, i).toString(&model, false));
}
}
curveValueCB->setCurrentIndex(curve.value);
break;
case CurveReference::CURVE_REF_CUSTOM:
{
int numcurves = getCurrentFirmware()->getCapability(NumCurves);
if (lastType != curve.type) {
lastType = curve.type;
curveValueCB->clear();
for (int i= ((flags & HIDE_NEGATIVE_CURVES) ? 0 : -numcurves); i<=numcurves; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, i).toString(&model, false), i);
if (i == curve.value) {
curveValueCB->setCurrentIndex(curveValueCB->count() - 1);
}
}
}
break;
}
default:
break;
}
}
lock = false;
}
void CurveGroup::gvarCBChanged(int state)
{
if (!lock) {
if (state) {
curve.value = 10000+1; // TODO constant in EEpromInterface ...
lastType = -1; // quickfix for issue #3518: force refresh of curveValueCB at next update() to set current index to GV1
}
else {
curve.value = 0; // TODO could be better
}
update();
}
}
void CurveGroup::typeChanged(int value)
{
if (!lock) {
int type = curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
switch (type) {
case 0:
curve = CurveReference(CurveReference::CURVE_REF_DIFF, 0);
break;
case 1:
curve = CurveReference(CurveReference::CURVE_REF_EXPO, 0);
break;
case 2:
curve = CurveReference(CurveReference::CURVE_REF_FUNC, 0);
break;
case 3:
curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, 0);
break;
}
update();
}
}
void CurveGroup::valuesChanged()
{
if (!lock) {
switch (curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt()) {
case 0:
case 1:
{
int value;
if (curveGVarCB->isChecked())
value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
else
value = curveValueSB->value();
curve = CurveReference(curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt() == 0 ? CurveReference::CURVE_REF_DIFF : CurveReference::CURVE_REF_EXPO, value);
break;
}
case 2:
curve = CurveReference(CurveReference::CURVE_REF_FUNC, curveValueCB->currentIndex());
break;
case 3:
curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, curveValueCB->itemData(curveValueCB->currentIndex()).toInt());
break;
}
update();
}
}
/*
* Helpers namespace functions
*/
@ -399,26 +235,6 @@ void Helpers::populateGVCB(QComboBox & b, int value, const ModelData & model)
b.setCurrentIndex(count);
}
// Returns Diff/Expo/Weight/Offset adjustment value as either a percentage or a global variable name.
QString Helpers::getAdjustmentString(int16_t val, const ModelData * model, bool sign)
{
QString ret;
if (val >= -10000 && val <= 10000) {
ret = "%1%";
if (sign && val > 0)
ret.prepend("+");
ret = ret.arg(val);
}
else {
ret = RawSource(SOURCE_TYPE_GVAR, abs(val) - 10001).toString(model);
if (val < 0)
ret.prepend("-");
else if (sign)
ret.prepend("+");
}
return ret;
}
// TODO: Move lookup to GVarData class (w/out combobox)
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
{
@ -742,7 +558,8 @@ GpsCoord extractGpsCoordinates(const QString & position)
return result;
}
TableLayout::TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels)
TableLayout::TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels) :
QObject(parent)
{
#if defined(TABLE_LAYOUT)
tableWidget = new QTableWidget(parent);

View file

@ -98,40 +98,10 @@ class GVarGroup: public QObject {
bool lock;
};
#define HIDE_DIFF 0x01
#define HIDE_EXPO 0x02
#define HIDE_NEGATIVE_CURVES 0x04
class CurveGroup : public QObject {
Q_OBJECT
public:
CurveGroup(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QComboBox *curveValueCB, QSpinBox *curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags=0);
void update();
protected slots:
void gvarCBChanged(int);
void typeChanged(int);
void valuesChanged();
protected:
QComboBox *curveTypeCB;
QCheckBox *curveGVarCB;
QComboBox *curveValueCB;
QSpinBox *curveValueSB;
CurveReference & curve;
const ModelData & model;
unsigned int flags;
bool lock;
int lastType;
};
namespace Helpers
{
void populateGvarUseCB(QComboBox *b, unsigned int phase);
void populateGVCB(QComboBox & b, int value, const ModelData & model);
QString getAdjustmentString(int16_t val, const ModelData * model = NULL, bool sign = false);
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
@ -208,8 +178,9 @@ private:
GpsCoord extractGpsCoordinates(const QString & position);
class TableLayout
class TableLayout: public QObject
{
Q_OBJECT
public:
TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels);
// ~TableLayout() ;

View file

@ -20,6 +20,7 @@
#include "channels.h"
#include "helpers.h"
#include "rawitemfilteredmodel.h"
LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel):
firmware(firmware),
@ -95,15 +96,17 @@ void LimitsGroup::updateMinMax(int max)
}
}
}
Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
ModelPanel(parent, model, generalSettings, firmware)
ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
commonItemModels(commonItemModels)
{
Stopwatch s1("Channels");
chnCapability = firmware->getCapability(Outputs);
int channelNameMaxLen = firmware->getCapability(ChannelsName);
curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this);
connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &ChannelsPanel::onModelDataAboutToBeUpdated);
connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &ChannelsPanel::onModelDataUpdateComplete);
QStringList headerLabels;
headerLabels << "#";
if (channelNameMaxLen > 0) {
@ -118,8 +121,6 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
headerLabels << tr("Linear Subtrim");
TableLayout *tableLayout = new TableLayout(this, chnCapability, headerLabels);
s1.report("header");
for (int i = 0; i < chnCapability; i++) {
int col = 0;
@ -165,6 +166,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
curveCB[i] = new QComboBox(this);
curveCB[i]->setProperty("index", i);
curveCB[i]->setModel(curveFilteredModel);
connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited()));
tableLayout->addWidget(i, col++, curveCB[i]);
}
@ -193,15 +195,13 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
}
}
update();
s1.report("add elements");
disableMouseScrolling();
tableLayout->resizeColumnsToContents();
tableLayout->pushRowsUp(chnCapability+1);
s1.report("end");
}
Channels::~Channels()
ChannelsPanel::~ChannelsPanel()
{
// compiler warning if delete[]
for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
@ -216,7 +216,7 @@ Channels::~Channels()
}
}
void Channels::symlimitsEdited()
void ChannelsPanel::symlimitsEdited()
{
if (!lock) {
QCheckBox *ckb = qobject_cast<QCheckBox*>(sender());
@ -226,17 +226,20 @@ void Channels::symlimitsEdited()
}
}
void Channels::nameEdited()
void ChannelsPanel::nameEdited()
{
if (!lock) {
QLineEdit *le = qobject_cast<QLineEdit*>(sender());
int index = le->property("index").toInt();
if (model->limitData[index].name != le->text()) {
strcpy(model->limitData[index].name, le->text().toLatin1());
updateItemModels();
emit modified();
}
}
}
void Channels::refreshExtendedLimits()
void ChannelsPanel::refreshExtendedLimits()
{
int channelMax = model->getChannelsMax();
@ -248,7 +251,7 @@ void Channels::refreshExtendedLimits()
emit modified();
}
void Channels::invEdited()
void ChannelsPanel::invEdited()
{
if (!lock) {
QComboBox *cb = qobject_cast<QComboBox*>(sender());
@ -258,17 +261,20 @@ void Channels::invEdited()
}
}
void Channels::curveEdited()
void ChannelsPanel::curveEdited()
{
if (!lock) {
QComboBox *cb = qobject_cast<QComboBox*>(sender());
int index = cb->property("index").toInt();
// ignore unnecessary updates that could be triggered by updates to the data model
if (model->limitData[index].curve != CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt())) {
model->limitData[index].curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt());
emit modified();
}
}
}
void Channels::ppmcenterEdited()
void ChannelsPanel::ppmcenterEdited()
{
if (!lock) {
QSpinBox *sb = qobject_cast<QSpinBox*>(sender());
@ -278,51 +284,49 @@ void Channels::ppmcenterEdited()
}
}
void Channels::update()
void ChannelsPanel::update()
{
for (int i = 0; i < chnCapability; i++) {
updateLine(i);
}
}
void Channels::updateLine(int i)
void ChannelsPanel::updateLine(int i)
{
lock = true;
LimitData &chn = model->limitData[i];
if (firmware->getCapability(ChannelsName) > 0) {
name[i]->setText(model->limitData[i].name);
name[i]->setText(chn.name);
}
chnOffset[i]->setValue(model->limitData[i].offset);
chnMin[i]->setValue(model->limitData[i].min);
chnMax[i]->setValue(model->limitData[i].max);
invCB[i]->setCurrentIndex((model->limitData[i].revert) ? 1 : 0);
chnOffset[i]->setValue(chn.offset);
chnMin[i]->setValue(chn.min);
chnMax[i]->setValue(chn.max);
invCB[i]->setCurrentIndex((chn.revert) ? 1 : 0);
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
int numcurves = firmware->getCapability(NumCurves);
curveCB[i]->clear();
for (int j = -numcurves; j <= numcurves; j++) {
curveCB[i]->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(model, false), j);
}
curveCB[i]->setCurrentIndex(model->limitData[i].curve.value + numcurves);
curveCB[i]->setCurrentIndex(curveCB[i]->findData(chn.curve.value));
}
if (firmware->getCapability(PPMCenter)) {
centerSB[i]->setValue(model->limitData[i].ppmCenter + 1500);
centerSB[i]->setValue(chn.ppmCenter + 1500);
}
if (firmware->getCapability(SYMLimits)) {
symlimitsChk[i]->setChecked(model->limitData[i].symetrical);
symlimitsChk[i]->setChecked(chn.symetrical);
}
lock = false;
}
void Channels::cmPaste()
void ChannelsPanel::cmPaste()
{
QByteArray data;
if (hasClipboardData(&data)) {
memcpy(&model->limitData[selectedIndex], data.constData(), sizeof(LimitData));
updateLine(selectedIndex);
updateItemModels();
emit modified();
}
}
void Channels::cmDelete()
void ChannelsPanel::cmDelete()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
@ -335,10 +339,11 @@ void Channels::cmDelete()
updateLine(i);
}
updateItemModels();
emit modified();
}
void Channels::cmCopy()
void ChannelsPanel::cmCopy()
{
QByteArray data;
data.append((char*)&model->limitData[selectedIndex], sizeof(LimitData));
@ -347,7 +352,7 @@ void Channels::cmCopy()
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
}
void Channels::cmCut()
void ChannelsPanel::cmCut()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
@ -356,7 +361,7 @@ void Channels::cmCut()
cmClear(false);
}
void Channels::onCustomContextMenuRequested(QPoint pos)
void ChannelsPanel::onCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
selectedIndex = label->property("index").toInt();
@ -378,7 +383,7 @@ void Channels::onCustomContextMenuRequested(QPoint pos)
contextMenu.exec(globalPos);
}
bool Channels::hasClipboardData(QByteArray * data) const
bool ChannelsPanel::hasClipboardData(QByteArray * data) const
{
const QClipboard * clipboard = QApplication::clipboard();
const QMimeData * mimeData = clipboard->mimeData();
@ -390,32 +395,32 @@ bool Channels::hasClipboardData(QByteArray * data) const
return false;
}
bool Channels::insertAllowed() const
bool ChannelsPanel::insertAllowed() const
{
return ((selectedIndex < chnCapability - 1) && (model->limitData[chnCapability - 1].isEmpty()));
}
bool Channels::moveDownAllowed() const
bool ChannelsPanel::moveDownAllowed() const
{
return selectedIndex < chnCapability - 1;
}
bool Channels::moveUpAllowed() const
bool ChannelsPanel::moveUpAllowed() const
{
return selectedIndex > 0;
}
void Channels::cmMoveUp()
void ChannelsPanel::cmMoveUp()
{
swapData(selectedIndex, selectedIndex - 1);
}
void Channels::cmMoveDown()
void ChannelsPanel::cmMoveDown()
{
swapData(selectedIndex, selectedIndex + 1);
}
void Channels::cmClear(bool prompt)
void ChannelsPanel::cmClear(bool prompt)
{
if (prompt) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
@ -425,10 +430,11 @@ void Channels::cmClear(bool prompt)
model->limitData[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
updateLine(selectedIndex);
updateItemModels();
emit modified();
}
void Channels::cmClearAll()
void ChannelsPanel::cmClearAll()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Channels. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
@ -438,19 +444,21 @@ void Channels::cmClearAll()
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, i);
updateLine(i);
}
updateItemModels();
emit modified();
}
void Channels::cmInsert()
void ChannelsPanel::cmInsert()
{
memmove(&model->limitData[selectedIndex + 1], &model->limitData[selectedIndex], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData));
model->limitData[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
update();
updateItemModels();
emit modified();
}
void Channels::swapData(int idx1, int idx2)
void ChannelsPanel::swapData(int idx1, int idx2)
{
if ((idx1 != idx2) && (!model->limitData[idx1].isEmpty() || !model->limitData[idx2].isEmpty())) {
LimitData chntmp = model->limitData[idx2];
@ -461,6 +469,23 @@ void Channels::swapData(int idx1, int idx2)
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
updateLine(idx1);
updateLine(idx2);
updateItemModels();
emit modified();
}
}
void ChannelsPanel::onModelDataAboutToBeUpdated()
{
lock = true;
}
void ChannelsPanel::onModelDataUpdateComplete()
{
update();
lock = false;
}
void ChannelsPanel::updateItemModels()
{
commonItemModels->update(CommonItemModels::RMO_CHANNELS);
}

View file

@ -26,6 +26,9 @@
#include <QtCore>
class CommonItemModels;
class RawItemFilteredModel;
constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel";
class GVarGroup;
@ -49,13 +52,13 @@ class LimitsGroup
double displayStep;
};
class Channels : public ModelPanel
class ChannelsPanel : public ModelPanel
{
Q_OBJECT
public:
Channels(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
~Channels();
ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
~ChannelsPanel();
public slots:
void refreshExtendedLimits();
@ -78,6 +81,8 @@ class Channels : public ModelPanel
void cmClear(bool prompt = true);
void cmClearAll();
void onCustomContextMenuRequested(QPoint pos);
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
bool hasClipboardData(QByteArray * data = nullptr) const;
@ -95,6 +100,9 @@ class Channels : public ModelPanel
QCheckBox *symlimitsChk[CPN_MAX_CHNOUT];
int selectedIndex;
int chnCapability;
CommonItemModels * commonItemModels;
RawItemFilteredModel *curveFilteredModel;
void updateItemModels();
};
#endif // _CHANNELS_H_

View file

@ -23,6 +23,7 @@
#include "node.h"
#include "edge.h"
#include "helpers.h"
#include "rawitemfilteredmodel.h"
#define GFX_MARGIN 16
@ -108,10 +109,11 @@ float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax
return y;
}
Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::Curves),
currentCurve(0)
currentCurve(0),
commonItemModels(commonItemModels)
{
ui->setupUi(this);
@ -230,12 +232,12 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
lock = false;
}
Curves::~Curves()
CurvesPanel::~CurvesPanel()
{
delete ui;
}
void Curves::editCurve()
void CurvesPanel::editCurve()
{
QPushButton *button = (QPushButton *)sender();
int index = button->property("index").toInt();
@ -243,7 +245,7 @@ void Curves::editCurve()
update();
}
void Curves::plotCurve(bool checked)
void CurvesPanel::plotCurve(bool checked)
{
QCheckBox *chk = (QCheckBox *)sender();
int index = chk->property("index").toInt();
@ -251,7 +253,7 @@ void Curves::plotCurve(bool checked)
updateCurve();
}
void Curves::update()
void CurvesPanel::update()
{
lock = true;
@ -266,12 +268,12 @@ void Curves::update()
lock = false;
}
void Curves::setCurrentCurve(int index)
void CurvesPanel::setCurrentCurve(int index)
{
currentCurve = index;
}
void Curves::updateCurveType()
void CurvesPanel::updateCurveType()
{
lock = true;
@ -297,7 +299,7 @@ void Curves::updateCurveType()
lock = false;
}
void Curves::updateCurve()
void CurvesPanel::updateCurve()
{
lock = true;
@ -371,7 +373,7 @@ void Curves::updateCurve()
lock = false;
}
void Curves::updateCurvePoints()
void CurvesPanel::updateCurvePoints()
{
lock = true;
@ -405,7 +407,7 @@ void Curves::updateCurvePoints()
lock = false;
}
void Curves::onPointEdited()
void CurvesPanel::onPointEdited()
{
if (!lock) {
int index = sender()->property("index").toInt();
@ -417,7 +419,7 @@ void Curves::onPointEdited()
}
}
void Curves::onNodeMoved(int x, int y)
void CurvesPanel::onNodeMoved(int x, int y)
{
if (!lock) {
lock = true;
@ -435,20 +437,20 @@ void Curves::onNodeMoved(int x, int y)
}
}
void Curves::onNodeFocus()
void CurvesPanel::onNodeFocus()
{
int index = sender()->property("index").toInt();
spny[index]->setFocus();
}
void Curves::onNodeUnfocus()
void CurvesPanel::onNodeUnfocus()
{
int index = sender()->property("index").toInt();
spny[index]->clearFocus();
updateCurve();
}
bool Curves::allowCurveType(int points, CurveData::CurveType type)
bool CurvesPanel::allowCurveType(int points, CurveData::CurveType type)
{
int totalpoints = 0;
for (int i = 0; i < maxCurves; i++) {
@ -466,7 +468,7 @@ bool Curves::allowCurveType(int points, CurveData::CurveType type)
}
}
void Curves::on_curvePoints_currentIndexChanged(int index)
void CurvesPanel::on_curvePoints_currentIndexChanged(int index)
{
if (!lock) {
int numpoints = ((QComboBox *)sender())->itemData(index).toInt();
@ -489,7 +491,7 @@ void Curves::on_curvePoints_currentIndexChanged(int index)
}
}
void Curves::on_curveCustom_currentIndexChanged(int index)
void CurvesPanel::on_curveCustom_currentIndexChanged(int index)
{
if (!lock) {
CurveData::CurveType type = (CurveData::CurveType)index;
@ -513,20 +515,23 @@ void Curves::on_curveCustom_currentIndexChanged(int index)
}
}
void Curves::on_curveSmooth_currentIndexChanged(int index)
void CurvesPanel::on_curveSmooth_currentIndexChanged(int index)
{
model->curves[currentCurve].smooth = index;
update();
}
void Curves::on_curveName_editingFinished()
void CurvesPanel::on_curveName_editingFinished()
{
if (ui->curveName->text() != model->curves[currentCurve].name) {
memset(model->curves[currentCurve].name, 0, sizeof(model->curves[currentCurve].name));
strcpy(model->curves[currentCurve].name, ui->curveName->text().toLatin1());
updateItemModels();
emit modified();
}
}
void Curves::resizeEvent(QResizeEvent *event)
void CurvesPanel::resizeEvent(QResizeEvent *event)
{
QRect qr = ui->curvePreview->contentsRect();
ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width() - GFX_MARGIN * 2, qr.height() - GFX_MARGIN * 2);
@ -534,7 +539,7 @@ void Curves::resizeEvent(QResizeEvent *event)
ModelPanel::resizeEvent(event);
}
void Curves::on_curveType_currentIndexChanged(int index)
void CurvesPanel::on_curveType_currentIndexChanged(int index)
{
unsigned int flags = templates[index].flags;
ui->curveCoeffLabel->setVisible(flags & CURVE_COEFF_ENABLE);
@ -548,7 +553,7 @@ void Curves::on_curveType_currentIndexChanged(int index)
ui->yMin->setValue(-100);
}
void Curves::addTemplate(QString name, unsigned int flags, curveFunction function)
void CurvesPanel::addTemplate(QString name, unsigned int flags, curveFunction function)
{
CurveCreatorTemplate tmpl;
tmpl.name = name;
@ -558,7 +563,7 @@ void Curves::addTemplate(QString name, unsigned int flags, curveFunction functio
ui->curveType->addItem(name);
}
void Curves::on_curveApply_clicked()
void CurvesPanel::on_curveApply_clicked()
{
int index = ui->curveType->currentIndex();
int numpoints = model->curves[currentCurve].count;
@ -595,14 +600,14 @@ void Curves::on_curveApply_clicked()
emit modified();
}
void Curves::onPointSizeEdited()
void CurvesPanel::onPointSizeEdited()
{
if (!lock) {
update();
}
}
void Curves::onNodeDelete()
void CurvesPanel::onNodeDelete()
{
int index = sender()->property("index").toInt();
int numpoints = model->curves[currentCurve].count;
@ -620,7 +625,7 @@ void Curves::onNodeDelete()
}
}
void Curves::onSceneNewPoint(int x, int y)
void CurvesPanel::onSceneNewPoint(int x, int y)
{
if ((model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) && (model->curves[currentCurve].count < CPN_MAX_POINTS)) {
int newidx = 0;
@ -651,7 +656,7 @@ void Curves::onSceneNewPoint(int x, int y)
}
}
void Curves::onCustomContextMenuRequested(QPoint pos)
void CurvesPanel::onCustomContextMenuRequested(QPoint pos)
{
QPushButton *button = (QPushButton *)sender();
selectedIndex = button->property("index").toInt();
@ -673,7 +678,7 @@ void Curves::onCustomContextMenuRequested(QPoint pos)
contextMenu.exec(globalPos);
}
bool Curves::hasClipboardData(QByteArray * data) const
bool CurvesPanel::hasClipboardData(QByteArray * data) const
{
const QClipboard * clipboard = QApplication::clipboard();
const QMimeData * mimeData = clipboard->mimeData();
@ -685,22 +690,22 @@ bool Curves::hasClipboardData(QByteArray * data) const
return false;
}
bool Curves::insertAllowed() const
bool CurvesPanel::insertAllowed() const
{
return ((selectedIndex < maxCurves - 1) && (model->curves[maxCurves - 1].isEmpty()));
}
bool Curves::moveDownAllowed() const
bool CurvesPanel::moveDownAllowed() const
{
return selectedIndex < maxCurves - 1;
}
bool Curves::moveUpAllowed() const
bool CurvesPanel::moveUpAllowed() const
{
return selectedIndex > 0;
}
void Curves::cmClear(bool prompt)
void CurvesPanel::cmClear(bool prompt)
{
if (prompt) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
@ -710,10 +715,11 @@ void Curves::cmClear(bool prompt)
model->curves[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
update();
updateItemModels();
emit modified();
}
void Curves::cmClearAll()
void CurvesPanel::cmClearAll()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Curves. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
@ -723,10 +729,11 @@ void Curves::cmClearAll()
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, i);
}
update();
updateItemModels();
emit modified();
}
void Curves::cmCopy()
void CurvesPanel::cmCopy()
{
QByteArray data;
data.append((char*)&model->curves[selectedIndex], sizeof(CurveData));
@ -735,7 +742,7 @@ void Curves::cmCopy()
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
}
void Curves::cmCut()
void CurvesPanel::cmCut()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
@ -743,7 +750,7 @@ void Curves::cmCut()
cmClear(false);
}
void Curves::cmDelete()
void CurvesPanel::cmDelete()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
@ -752,40 +759,43 @@ void Curves::cmDelete()
model->curves[maxCurves - 1].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
update();
updateItemModels();
emit modified();
}
void Curves::cmInsert()
void CurvesPanel::cmInsert()
{
memmove(&model->curves[selectedIndex + 1], &model->curves[selectedIndex], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
model->curves[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
update();
updateItemModels();
emit modified();
}
void Curves::cmMoveDown()
void CurvesPanel::cmMoveDown()
{
swapData(selectedIndex, selectedIndex + 1);
}
void Curves::cmMoveUp()
void CurvesPanel::cmMoveUp()
{
swapData(selectedIndex, selectedIndex - 1);
}
void Curves::cmPaste()
void CurvesPanel::cmPaste()
{
QByteArray data;
if (hasClipboardData(&data)) {
CurveData *cd = &model->curves[selectedIndex];
memcpy(cd, data.constData(), sizeof(CurveData));
update();
updateItemModels();
emit modified();
}
}
void Curves::swapData(int idx1, int idx2)
void CurvesPanel::swapData(int idx1, int idx2)
{
if ((idx1 != idx2) && (!model->curves[idx1].isEmpty() || !model->curves[idx2].isEmpty())) {
CurveData cdtmp = model->curves[idx2];
@ -795,10 +805,16 @@ void Curves::swapData(int idx1, int idx2)
memcpy(cd1, &cdtmp, sizeof(CurveData));
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
update();
updateItemModels();
emit modified();
}
}
void CurvesPanel::updateItemModels()
{
commonItemModels->update(CommonItemModels::RMO_CURVES);
}
CustomScene::CustomScene(QGraphicsView * view) :
QGraphicsScene(view)
{

View file

@ -26,6 +26,8 @@
#include <QGraphicsScene>
#include <QGraphicsView>
class CommonItemModels;
constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve";
namespace Ui {
@ -54,13 +56,13 @@ class CustomScene : public QGraphicsScene
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event) override;
};
class Curves : public ModelPanel
class CurvesPanel : public ModelPanel
{
Q_OBJECT
public:
Curves(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
virtual ~Curves();
CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~CurvesPanel();
virtual void update();
@ -119,6 +121,8 @@ class Curves : public ModelPanel
bool moveDownAllowed() const;
bool moveUpAllowed() const;
void swapData(int idx1, int idx2);
CommonItemModels * commonItemModels;
void updateItemModels();
};
#endif // _CURVES_H_

View file

@ -66,20 +66,32 @@ void RepeatComboBox::update()
setCurrentIndex(value);
}
CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware):
CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
GenericPanel(parent, model, generalSettings, firmware),
functions(model ? model->customFn : generalSettings.customFn),
commonItemModels(commonItemModels),
mediaPlayerCurrent(-1),
mediaPlayer(nullptr)
mediaPlayer(nullptr),
modelsUpdateCnt(0)
{
Stopwatch s1("CustomFunctionsPanel - populate");
lock = true;
fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions);
rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, model, model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext, this);
rawSrcAllItemModel = new RawSourceFilterItemModel(&generalSettings, model, this);
rawSrcInputsItemModel = new RawSourceFilterItemModel(rawSrcAllItemModel->sourceModel(), RawSource::InputSourceGroups, this);
rawSrcGVarsItemModel = new RawSourceFilterItemModel(rawSrcAllItemModel->sourceModel(), RawSource::GVarsGroup, this);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext, this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete);
rawSourceAllModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this);
connect(rawSourceAllModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated);
connect(rawSourceAllModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete);
rawSourceInputsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this);
connect(rawSourceInputsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated);
connect(rawSourceInputsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete);
rawSourceGVarsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::GVarsGroup, this);
connect(rawSourceGVarsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated);
connect(rawSourceGVarsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete);
if (!firmware->getCapability(VoicesAsNumbers)) {
tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength));
@ -93,8 +105,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
}
}
s1.report("get tracks");
if (IS_STM32(firmware->getBoard())) {
scriptsSet = getFilesSet(g.profile[g.id()].sdPath() + "/SCRIPTS/FUNCTIONS", QStringList() << "*.lua", firmware->getCapability(VoicesMaxLength));
for (int i = 0; i < fswCapability; i++) {
@ -106,7 +116,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
}
}
}
s1.report("get scripts");
CompanionIcon playIcon("play.png");
playIcon.addImage("stop.png", QIcon::Normal, QIcon::On);
@ -133,7 +142,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
// The switch
fswtchSwtch[i] = new QComboBox(this);
fswtchSwtch[i]->setModel(rawSwitchItemModel);
fswtchSwtch[i]->setModel(rawSwitchFilteredModel);
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
fswtchSwtch[i]->setProperty("index", i);
fswtchSwtch[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
@ -198,7 +207,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
fswtchParamArmT[i]->setEditable(true);
fswtchParamArmT[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
paramLayout->addWidget(fswtchParamArmT[i]);
connect(fswtchParamArmT[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
connect(fswtchParamArmT[i], SIGNAL(editTextChanged ( const QString)), this, SLOT(customFunctionEdited()));
@ -222,7 +230,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
tableLayout->addLayout(i, 4, repeatLayout);
fswtchRepeat[i] = new RepeatComboBox(this, functions[i].repeatParam);
repeatLayout->addWidget(fswtchRepeat[i], i + 1);
connect(fswtchRepeat[i], SIGNAL(modified()), this, SLOT(onChildModified()));
connect(fswtchRepeat[i], SIGNAL(modified()), this, SLOT(onRepeatModified()));
fswtchEnable[i] = new QCheckBox(this);
fswtchEnable[i]->setProperty("index", i);
@ -232,20 +240,13 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
connect(fswtchEnable[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited()));
}
s1.report("add items");
disableMouseScrolling();
s1.report("disableMouseScrolling");
lock = false;
update();
s1.report("update");
tableLayout->resizeColumnsToContents();
s1.report("resizeColumnsToContents");
tableLayout->setColumnWidth(3, 300);
tableLayout->pushRowsUp(fswCapability + 1);
s1.report("end");
update();
lock = false;
}
CustomFunctionsPanel::~CustomFunctionsPanel()
@ -254,15 +255,6 @@ CustomFunctionsPanel::~CustomFunctionsPanel()
stopSound(mediaPlayerCurrent);
}
void CustomFunctionsPanel::updateDataModels()
{
const bool oldLock = lock;
lock = true;
rawSwitchItemModel->update();
rawSrcAllItemModel->update();
lock = oldLock;
}
void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state)
{
if (state != QMediaPlayer::PlayingState)
@ -343,6 +335,7 @@ void CustomFunctionsPanel::toggleSound(bool play)
#define CUSTOM_FUNCTION_BL_COLOR (1<<9)
#define CUSTOM_FUNCTION_SHOW_FUNC (1<<10)
void CustomFunctionsPanel::customFunctionEdited()
{
if (!lock) {
@ -369,7 +362,7 @@ void CustomFunctionsPanel::functionEdited()
}
}
void CustomFunctionsPanel::onChildModified()
void CustomFunctionsPanel::onRepeatModified()
{
emit modified();
}
@ -385,6 +378,10 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
cfn.func = func;
cfn.enabled = fswtchEnable[i]->isChecked();
}
else {
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(cfn.swtch.toValue()));
fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(cfn.func));
}
if (!cfn.isEmpty()) {
widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC;
@ -459,7 +456,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
fswtchParamTime[i]->setTime(cfn.param);
widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM | CUSTOM_FUNCTION_ENABLE;
}
else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) {
else if (func >= FuncSetFailsafe && func <= FuncBindExternalModule) {
widgetsMask |= CUSTOM_FUNCTION_ENABLE;
}
else if (func == FuncVolume || func == FuncBacklight) {
@ -585,7 +582,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
void CustomFunctionsPanel::update()
{
updateDataModels();
lock = true;
for (int i = 0; i < fswCapability; i++) {
refreshCustomFunction(i);
@ -711,21 +707,21 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi
CustomFunctionData::populateResetParams(model, b, value);
}
else if (function == FuncVolume || function == FuncBacklight) {
b->setModel(rawSrcInputsItemModel);
b->setModel(rawSourceInputsModel);
b->setCurrentIndex(b->findData(value));
}
else if (function == FuncPlayValue) {
b->setModel(rawSrcAllItemModel);
b->setModel(rawSourceAllModel);
b->setCurrentIndex(b->findData(value));
}
else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) {
switch (adjustmode) {
case 1:
b->setModel(rawSrcInputsItemModel);
b->setModel(rawSourceInputsModel);
b->setCurrentIndex(b->findData(value));
break;
case 2:
b->setModel(rawSrcGVarsItemModel);
b->setModel(rawSourceGVarsModel);
b->setCurrentIndex(b->findData(value));
break;
}
@ -830,3 +826,23 @@ bool CustomFunctionsPanel::moveUpAllowed() const
{
return selectedIndex > 0;
}
void CustomFunctionsPanel::onModelDataAboutToBeUpdated()
{
lock = true;
modelsUpdateCnt++;
}
void CustomFunctionsPanel::onModelDataUpdateComplete()
{
modelsUpdateCnt--;
if (modelsUpdateCnt < 1) {
lock = true;
for (int i = 0; i < fswCapability; i++) {
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(functions[i].func));
}
update();
lock = false;
}
}

View file

@ -26,8 +26,8 @@
#include <QMediaPlayer>
class RawSourceFilterItemModel;
class RawSwitchFilterItemModel;
class CommonItemModels;
class RawItemFilteredModel;
class TimerEdit;
constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function";
@ -55,7 +55,7 @@ class CustomFunctionsPanel : public GenericPanel
Q_OBJECT
public:
CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware);
CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
~CustomFunctionsPanel();
virtual void update();
@ -64,12 +64,11 @@ class CustomFunctionsPanel : public GenericPanel
CustomFunctionData * functions;
private slots:
void updateDataModels();
void customFunctionEdited();
void functionEdited();
void onCustomContextMenuRequested(QPoint pos);
void refreshCustomFunction(int index, bool modified=false);
void onChildModified();
void onRepeatModified();
bool playSound(int index);
void stopSound(int index);
void toggleSound(bool play);
@ -84,6 +83,8 @@ class CustomFunctionsPanel : public GenericPanel
void cmInsert();
void cmClear(bool prompt = true);
void cmClearAll();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
void populateFuncCB(QComboBox *b, unsigned int value);
@ -95,10 +96,11 @@ class CustomFunctionsPanel : public GenericPanel
bool moveUpAllowed() const;
void swapData(int idx1, int idx2);
void resetCBsAndRefresh(int idx);
RawSwitchFilterItemModel * rawSwitchItemModel;
RawSourceFilterItemModel * rawSrcAllItemModel;
RawSourceFilterItemModel * rawSrcInputsItemModel;
RawSourceFilterItemModel * rawSrcGVarsItemModel;
CommonItemModels * commonItemModels;
RawItemFilteredModel * rawSwitchFilteredModel;
RawItemFilteredModel * rawSourceAllModel;
RawItemFilteredModel * rawSourceInputsModel;
RawItemFilteredModel * rawSourceGVarsModel;
QSet<QString> tracksSet;
QSet<QString> scriptsSet;
@ -119,7 +121,7 @@ class CustomFunctionsPanel : public GenericPanel
int selectedIndex;
int fswCapability;
int modelsUpdateCnt;
};
#endif // _CUSTOMFUNCTIONS_H_

View file

@ -24,7 +24,8 @@
#include "helpers.h"
ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings,
Firmware * firmware, QString & inputName) :
Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceModel,
RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) :
QDialog(parent),
ui(new Ui::ExpoDialog),
model(model),
@ -36,6 +37,7 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
lock(false)
{
ui->setupUi(this);
QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 };
QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 };
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
@ -48,11 +50,9 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
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);
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, curveItemModel, this);
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model,
firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES));
ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this));
ui->switchesCB->setModel(rawSwitchModel);
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue()));
ui->sideCB->setCurrentIndex(ed->mode - 1);
@ -83,9 +83,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
if (firmware->getCapability(VirtualInputs)) {
ui->inputName->setMaxLength(firmware->getCapability(InputsLength));
ui->sourceCB->setModel(new RawSourceFilterItemModel(&generalSettings, &model, (RawSource::InputSourceGroups & ~RawSource::InputsGroup) | RawSource::TelemGroup, this));
ui->sourceCB->setModel(rawSourceModel);
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue()));
ui->sourceCB->removeItem(0);
ui->inputName->setValidator(new QRegExpValidator(rx, this));
ui->inputName->setText(inputName);
}
@ -138,7 +137,6 @@ ExpoDialog::~ExpoDialog()
{
delete gvWeightGroup;
delete gvOffsetGroup;
delete curveGroup;
delete ui;
}

View file

@ -26,7 +26,8 @@
#include "modelprinter.h"
class GVarGroup;
class CurveGroup;
class RawItemFilteredModel;
class CurveReferenceUIManager;
namespace Ui {
class ExpoDialog;
@ -36,7 +37,8 @@ class ExpoDialog : public QDialog {
Q_OBJECT
public:
ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings,
Firmware * firmware, QString & inputName);
Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceItemModel,
RawItemFilteredModel * rawSwitchItemModel, RawItemFilteredModel * curveItemModel);
~ExpoDialog();
protected:
@ -59,7 +61,7 @@ class ExpoDialog : public QDialog {
QString & inputName;
GVarGroup * gvWeightGroup;
GVarGroup * gvOffsetGroup;
CurveGroup * curveGroup;
CurveReferenceUIManager * curveGroup;
ModelPrinter modelPrinter;
bool lock;
QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES];

View file

@ -24,14 +24,15 @@
#include "helpers.h"
#include "customdebug.h"
FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchFilterItemModel * switchModel):
FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::FlightMode),
phaseIdx(phaseIdx),
phase(model.flightModeData[phaseIdx]),
rawSwitchItemModel(NULL)
phase(model.flightModeData[phaseIdx])
{
ui->setupUi(this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &FlightModePanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &FlightModePanel::onModelDataUpdateComplete);
ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu);
ui->labelName->setToolTip(tr("Popup menu available"));
@ -56,8 +57,8 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
// Flight mode switch
if (phaseIdx > 0) {
ui->swtch->setModel(switchModel);
connect(ui->swtch, SIGNAL(activated(int)), this, SLOT(phaseSwitchChanged(int)));
ui->swtch->setModel(rawSwitchFilteredModel);
connect(ui->swtch, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseSwitch_currentIndexChanged(int)));
}
else {
ui->swtch->hide();
@ -316,8 +317,6 @@ void FlightModePanel::update()
for (int i = 0; i < reCount; i++) {
updateRotaryEncoder(i);
}
emit nameModified();
}
void FlightModePanel::updateGVar(int index)
@ -390,17 +389,18 @@ void FlightModePanel::phaseName_editingFinished()
{
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
strcpy(phase.name, lineEdit->text().toLatin1());
emit phaseNameChanged();
emit modified();
emit nameModified();
}
void FlightModePanel::phaseSwitchChanged(int index)
void FlightModePanel::phaseSwitch_currentIndexChanged(int index)
{
if (!lock) {
bool ok;
const RawSwitch rs(ui->swtch->itemData(index).toInt(&ok));
if (ok && phase.swtch.toValue() != rs.toValue()) {
phase.swtch = rs;
emit phaseSwitchChanged();
emit modified();
}
}
@ -457,7 +457,7 @@ void FlightModePanel::phaseGVValue_editingFinished()
QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox*>(sender());
int gvar = spinBox->property("index").toInt();
phase.gvars[gvar] = spinBox->value() * model->gvarData[gvar].multiplierSet();
emit datachanged();
updateGVar(gvar);
emit modified();
}
}
@ -469,7 +469,7 @@ void FlightModePanel::GVName_editingFinished()
int gvar = lineedit->property("index").toInt();
memset(&model->gvarData[gvar].name, 0, sizeof(model->gvarData[gvar].name));
strcpy(model->gvarData[gvar].name, lineedit->text().toLatin1());
emit datachanged();
emit gvNameChanged();
emit modified();
}
}
@ -488,7 +488,7 @@ void FlightModePanel::phaseGVUse_currentIndexChanged(int index)
}
if (model->isGVarLinkedCircular(phaseIdx, gvar))
QMessageBox::warning(this, "Companion", tr("Warning: Global variable links back to itself. Flight Mode 0 value used."));
emit datachanged();
updateGVar(gvar);
emit modified();
lock = false;
}
@ -500,7 +500,7 @@ void FlightModePanel::phaseGVUnit_currentIndexChanged(int index)
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int gvar = comboBox->property("index").toInt();
model->gvarData[gvar].unit = index;
emit datachanged();
updateGVar(gvar);
emit modified();
}
}
@ -511,7 +511,7 @@ void FlightModePanel::phaseGVPrec_currentIndexChanged(int index)
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int gvar = comboBox->property("index").toInt();
model->gvarData[gvar].prec = index;
emit datachanged();
updateGVar(gvar);
emit modified();
}
}
@ -534,7 +534,7 @@ void FlightModePanel::phaseGVMin_editingFinished()
}
}
}
emit datachanged();
updateGVar(gvar);
emit modified();
}
}
@ -557,7 +557,7 @@ void FlightModePanel::phaseGVMax_editingFinished()
}
}
}
emit datachanged();
updateGVar(gvar);
emit modified();
}
}
@ -741,7 +741,8 @@ void FlightModePanel::cmClear(bool prompt)
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, phaseIdx);
emit datachanged();
update();
emit phaseDataChanged();
emit modified();
}
@ -767,7 +768,7 @@ void FlightModePanel::cmClearAll()
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
}
emit datachanged();
emit phaseDataChanged();
emit modified();
}
@ -846,7 +847,7 @@ void FlightModePanel::cmDelete()
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, -1);
emit datachanged();
emit phaseDataChanged();
emit modified();
}
@ -897,7 +898,7 @@ void FlightModePanel::cmInsert()
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, 1);
emit datachanged();
emit phaseDataChanged();
emit modified();
}
@ -946,7 +947,7 @@ void FlightModePanel::cmPaste()
}
}
emit datachanged();
emit phaseDataChanged();
emit modified();
}
}
@ -1035,7 +1036,7 @@ void FlightModePanel::swapData(int idx1, int idx2)
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
emit datachanged();
emit phaseDataChanged();
emit modified();
}
@ -1162,7 +1163,8 @@ void FlightModePanel::gvCmClear(bool prompt)
}
phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx);
}
emit datachanged();
updateGVar(gvIdx);
emit gvNameChanged();
emit modified();
}
@ -1186,7 +1188,10 @@ void FlightModePanel::gvCmClearAll()
phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx);
}
}
emit datachanged();
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
emit gvNameChanged();
emit modified();
}
@ -1261,8 +1266,13 @@ void FlightModePanel::gvCmDelete()
for (int j = 0; j < fmCount; j++) {
model->flightModeData[j].gvars[maxidx] = model->flightModeData[j].linkedGVarFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, -1);
emit datachanged();
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
emit gvNameChanged();
emit modified();
}
@ -1279,7 +1289,10 @@ void FlightModePanel::gvCmInsert()
model->flightModeData[j].gvars[gvIdx] = model->flightModeData[j].linkedGVarFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, 1);
emit datachanged();
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
emit gvNameChanged();
emit modified();
}
@ -1322,7 +1335,8 @@ void FlightModePanel::gvCmPaste()
else
phase.gvars[gvIdx] = val;
}
emit datachanged();
updateGVar(gvIdx);
emit gvNameChanged();
emit modified();
}
@ -1340,33 +1354,51 @@ void FlightModePanel::gvSwapData(int idx1, int idx2)
model->flightModeData[j].gvars[idx1] = valtmp;
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
emit datachanged();
updateGVar(idx1);
updateGVar(idx2);
emit gvNameChanged();
emit modified();
}
}
void FlightModePanel::onModelDataAboutToBeUpdated()
{
lock = true;
}
void FlightModePanel::onModelDataUpdateComplete()
{
update();
lock = false;
}
/**********************************************************/
FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
modesCount(firmware->getCapability(FlightModes))
commonItemModels(commonItemModels)
{
RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this);
connect(this, &FlightModesPanel::updated, swModel, &RawSwitchFilterItemModel::update);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this);
modesCount = firmware->getCapability(FlightModes);
QGridLayout * gridLayout = new QGridLayout(this);
tabWidget = new QTabWidget(this);
for (int i = 0; i < modesCount; i++) {
FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, swModel);
FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, rawSwitchFilteredModel);
tab->setProperty("index", i);
connect(tab, &FlightModePanel::datachanged, this, &FlightModesPanel::update);
connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified);
connect(tab, &FlightModePanel::nameModified, this, &FlightModesPanel::onPhaseNameChanged);
connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::onPhaseNameChanged);
connect(tab, &FlightModePanel::phaseNameChanged, this, &FlightModesPanel::onPhaseNameChanged);
connect(tab, &FlightModePanel::phaseSwitchChanged, this, &FlightModesPanel::updateItemModels);
connect(tab, &FlightModePanel::gvNameChanged, this, &FlightModesPanel::updateItemModels);
connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update);
tabWidget->addTab(tab, getTabName(i));
panels << tab;
}
connect(tabWidget, &QTabWidget::currentChanged, this, &FlightModesPanel::onTabIndexChanged);
gridLayout->addWidget(tabWidget, 0, 0, 1, 1);
onTabIndexChanged(0);
}
FlightModesPanel::~FlightModesPanel()
@ -1391,9 +1423,22 @@ void FlightModesPanel::onPhaseNameChanged()
{
int index = sender()->property("index").toInt();
tabWidget->setTabText(index, getTabName(index));
updateItemModels();
}
void FlightModesPanel::update()
{
emit updated();
}
void FlightModesPanel::updateItemModels()
{
commonItemModels->update(CommonItemModels::RMO_FLIGHT_MODES);
commonItemModels->update(CommonItemModels::RMO_GLOBAL_VARIABLES);
}
void FlightModesPanel::onTabIndexChanged(int index)
{
if (index < panels.size())
panels.at(index)->update();
}

View file

@ -24,7 +24,8 @@
#include "modeledit.h"
#include "eeprominterface.h"
class RawSwitchFilterItemModel;
class CommonItemModels;
class RawItemFilteredModel;
constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode";
constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params";
@ -40,18 +41,20 @@ class FlightModePanel : public ModelPanel
Q_OBJECT
public:
FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchFilterItemModel * switchModel);
FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel);
virtual ~FlightModePanel();
virtual void update();
signals:
void nameModified();
void datachanged();
void gvNameChanged();
void phaseDataChanged();
void phaseNameChanged();
void phaseSwitchChanged();
private slots:
void phaseName_editingFinished();
void phaseSwitchChanged(int index);
void phaseSwitch_currentIndexChanged(int index);
void phaseFadeIn_editingFinished();
void phaseFadeOut_editingFinished();
void phaseTrimUse_currentIndexChanged(int index);
@ -87,6 +90,8 @@ class FlightModePanel : public ModelPanel
void gvCmPaste();
void gvCmMoveDown();
void gvCmMoveUp();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
Ui::FlightMode *ui;
@ -111,7 +116,6 @@ class FlightModePanel : public ModelPanel
QVector<QComboBox *> trimsUse;
QVector<QSpinBox *> trimsValue;
QVector<QSlider *> trimsSlider;
RawSwitchFilterItemModel * rawSwitchItemModel;
Board::Type board;
void trimUpdate(unsigned int trim);
@ -141,7 +145,7 @@ class FlightModesPanel : public ModelPanel
Q_OBJECT
public:
FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~FlightModesPanel();
public slots:
@ -152,13 +156,17 @@ class FlightModesPanel : public ModelPanel
private slots:
void onPhaseNameChanged();
void onTabIndexChanged(int index);
private:
QString getTabName(int index);
int modesCount;
QTabWidget *tabWidget;
CommonItemModels *commonItemModels;
RawItemFilteredModel *rawSwitchFilteredModel;
QVector<GenericPanel *> panels;
void updateItemModels();
};
#endif // _FLIGHTMODES_H_

View file

@ -23,19 +23,26 @@
#include "helpers.h"
#include "rawitemfilteredmodel.h"
HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::Heli)
ui(new Ui::Heli),
commonItemModels(commonItemModels)
{
ui->setupUi(this);
rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, RawSource::InputSourceGroups, this);
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &HeliPanel::onModelDataAboutToBeUpdated);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &HeliPanel::onModelDataUpdateComplete);
connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited()));
ui->swashCollectiveSource->setModel(rawSourceFilteredModel);
connect(ui->swashCollectiveSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
if (firmware->getCapability(VirtualInputs)) {
ui->swashAileronSource->setModel(rawSourceFilteredModel);
connect(ui->swashAileronSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
ui->swashElevatorSource->setModel(rawSourceFilteredModel);
connect(ui->swashElevatorSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
connect(ui->swashAileronWeight, SIGNAL(editingFinished()), this, SLOT(edited()));
connect(ui->swashElevatorWeight, SIGNAL(editingFinished()), this, SLOT(edited()));
@ -66,27 +73,15 @@ HeliPanel::~HeliPanel()
delete ui;
}
void HeliPanel::updateDataModels()
{
const bool oldLock = lock;
lock = true;
rawSourceItemModel->update();
lock = oldLock;
}
void HeliPanel::update()
{
lock = true;
updateDataModels();
ui->swashType->setCurrentIndex(model->swashRingData.type);
ui->swashCollectiveSource->setModel(rawSourceItemModel);
ui->swashCollectiveSource->setCurrentIndex(ui->swashCollectiveSource->findData(model->swashRingData.collectiveSource.toValue()));
ui->swashRingVal->setValue(model->swashRingData.value);
if (firmware->getCapability(VirtualInputs)) {
ui->swashElevatorSource->setModel(rawSourceItemModel);
ui->swashElevatorSource->setCurrentIndex(ui->swashElevatorSource->findData(model->swashRingData.elevatorSource.toValue()));
ui->swashAileronSource->setModel(rawSourceItemModel);
ui->swashAileronSource->setCurrentIndex(ui->swashAileronSource->findData(model->swashRingData.aileronSource.toValue()));
ui->swashElevatorWeight->setValue(model->swashRingData.elevatorWeight);
ui->swashAileronWeight->setValue(model->swashRingData.aileronWeight);
@ -122,3 +117,14 @@ void HeliPanel::edited()
emit modified();
}
}
void HeliPanel::onModelDataAboutToBeUpdated()
{
lock = true;
}
void HeliPanel::onModelDataUpdateComplete()
{
update();
lock = false;
}

View file

@ -23,7 +23,8 @@
#include "modeledit.h"
class RawSourceFilterItemModel;
class CommonItemModels;
class RawItemFilteredModel;
namespace Ui {
class Heli;
@ -34,17 +35,19 @@ class HeliPanel : public ModelPanel
Q_OBJECT
public:
HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
~HeliPanel();
void update();
private slots:
void updateDataModels();
void edited();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
Ui::Heli *ui;
RawSourceFilterItemModel * rawSourceItemModel;
CommonItemModels * commonItemModels;
RawItemFilteredModel * rawSourceFilteredModel;
};
#endif // _HELI_H_

View file

@ -21,12 +21,26 @@
#include "inputs.h"
#include "expodialog.h"
#include "helpers.h"
#include "rawitemfilteredmodel.h"
InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
expoInserted(false),
modelPrinter(firmware, generalSettings, model)
modelPrinter(firmware, generalSettings, model),
commonItemModels(commonItemModels)
{
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), (RawSource::InputSourceGroups & ~ RawSource::NoneGroup & ~RawSource::InputsGroup), this);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete);
curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this);
connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated);
connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete);
inputsCount = firmware->getCapability(VirtualInputs);
if (inputsCount == 0)
inputsCount = CPN_MAX_STICKS;
@ -180,13 +194,14 @@ void InputsPanel::gm_openExpo(int index)
if (firmware->getCapability(VirtualInputs))
inputName = model->inputNames[ed.chn];
ExpoDialog *g = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName);
if (g->exec()) {
ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel);
if (dlg->exec()) {
model->expoData[index] = ed;
if (firmware->getCapability(VirtualInputs))
strncpy(model->inputNames[ed.chn], inputName.toLatin1().data(), INPUT_NAME_LEN);
emit modified();
update();
updateItemModels();
emit modified();
}
else {
if (expoInserted) {
@ -195,6 +210,7 @@ void InputsPanel::gm_openExpo(int index)
expoInserted=false;
update();
}
delete dlg;
}
int InputsPanel::getExpoIndex(unsigned int dch)
@ -239,8 +255,9 @@ void InputsPanel::exposDelete(bool prompt)
}
exposDeleteList(list, prompt);
emit modified();
update();
updateItemModels();
emit modified();
}
void InputsPanel::exposCut()
@ -313,8 +330,9 @@ void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx)
i += sizeof(ExpoData);
}
emit modified();
update();
updateItemModels();
emit modified();
}
}
@ -481,8 +499,9 @@ void InputsPanel::moveExpoList(bool down)
}
}
if (mod) {
emit modified();
update();
updateItemModels();
emit modified();
}
setSelectedByExpoList(highlightList);
}
@ -520,8 +539,9 @@ void InputsPanel::clearExpos()
for (int i = 0; i < inputsCount; i++) {
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, i);
}
emit modified();
update();
updateItemModels();
emit modified();
}
}
@ -569,6 +589,7 @@ void InputsPanel::cmInputClear()
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, inputIdx);
update();
updateItemModels();
emit modified();
}
@ -592,6 +613,7 @@ void InputsPanel::cmInputDelete()
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SHIFT, inputIdx, 0, -1);
update();
updateItemModels();
emit modified();
}
@ -610,6 +632,7 @@ void InputsPanel::cmInputInsert()
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SHIFT, inputIdx, 0, 1);
update();
updateItemModels();
emit modified();
}
@ -671,6 +694,7 @@ void InputsPanel::cmInputSwapData(int idx1, int idx2)
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
update();
updateItemModels();
emit modified();
}
@ -705,3 +729,19 @@ int InputsPanel::getInputIndexFromSelected()
}
return idx;
}
void InputsPanel::onModelDataAboutToBeUpdated()
{
lock = true;
}
void InputsPanel::onModelDataUpdateComplete()
{
update();
lock = false;
}
void InputsPanel::updateItemModels()
{
commonItemModels->update(CommonItemModels::RMO_INPUTS);
}

View file

@ -25,6 +25,9 @@
#include "mixerslistwidget.h"
#include "modelprinter.h"
class CommonItemModels;
class RawItemFilteredModel;
constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo";
class InputsPanel : public ModelPanel
@ -32,7 +35,7 @@ class InputsPanel : public ModelPanel
Q_OBJECT
public:
InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~InputsPanel();
virtual void update();
@ -59,6 +62,8 @@ class InputsPanel : public ModelPanel
void cmInputInsert();
void cmInputMoveDown();
void cmInputMoveUp();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
bool expoInserted;
@ -67,6 +72,10 @@ class InputsPanel : public ModelPanel
ModelPrinter modelPrinter;
int selectedIdx;
int inputIdx;
CommonItemModels * commonItemModels;
RawItemFilteredModel *rawSourceFilteredModel;
RawItemFilteredModel *rawSwitchFilteredModel;
RawItemFilteredModel *curveFilteredModel;
int getExpoIndex(unsigned int dch);
bool gm_insertExpo(int idx);
@ -87,6 +96,7 @@ class InputsPanel : public ModelPanel
bool isExpoIndex(const int index);
int getIndexFromSelected();
int getInputIndexFromSelected();
void updateItemModels();
};
#endif // _INPUTS_H_

View file

@ -24,16 +24,20 @@
#include <TimerEdit>
LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
selectedIndex(0)
commonItemModels(commonItemModels),
selectedIndex(0),
modelsUpdateCnt(0)
{
Stopwatch s1("LogicalSwitchesPanel");
rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::LogicalSwitchesContext, this);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::LogicalSwitchesContext, this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete);
const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup);
rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, srcGroups, this);
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), srcGroups, this);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete);
lsCapability = firmware->getCapability(LogicalSwitches);
lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt);
@ -45,11 +49,8 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
}
TableLayout * tableLayout = new TableLayout(this, lsCapability, headerLabels);
s1.report("header");
const int channelsMax = model.getChannelsMax(true);
lock = true;
for (int i = 0; i < lsCapability; i++) {
// The label
QLabel * label = new QLabel(this);
@ -123,7 +124,8 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
// AND
cbAndSwitch[i] = new QComboBox(this);
cbAndSwitch[i]->setProperty("index", i);
populateAndSwitchCB(cbAndSwitch[i]);
cbAndSwitch[i]->setModel(rawSwitchFilteredModel);
cbAndSwitch[i]->setVisible(true);
connect(cbAndSwitch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onAndSwitchChanged(int)));
tableLayout->addWidget(i, 4, cbAndSwitch[i]);
@ -152,43 +154,30 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
}
}
s1.report("added elements");
disableMouseScrolling();
lock = false;
update();
tableLayout->resizeColumnsToContents();
tableLayout->pushRowsUp(lsCapability+1);
s1.report("end");
}
LogicalSwitchesPanel::~LogicalSwitchesPanel()
{
}
void LogicalSwitchesPanel::updateDataModels()
{
const bool oldLock = lock;
lock = true;
rawSwitchItemModel->update();
rawSourceItemModel->update();
lock = oldLock;
}
void LogicalSwitchesPanel::onFunctionChanged()
{
if (!lock) {
int i = sender()->property("index").toInt();
unsigned newFunc = cbFunction[i]->currentData().toUInt();
if (model->logicalSw[i].func == newFunc)
return;
const unsigned oldFunc = model->logicalSw[i].func;
unsigned oldFunc = model->logicalSw[i].func;
CSFunctionFamily oldFuncFamily = model->logicalSw[i].getFunctionFamily();
model->logicalSw[i].func = newFunc;
CSFunctionFamily newFuncFamily = model->logicalSw[i].getFunctionFamily();
if (oldFuncFamily != newFuncFamily) {
if (oldFuncFamily != newFuncFamily || newFunc == LS_FN_OFF) {
model->logicalSw[i].clear();
model->logicalSw[i].func = newFunc;
if (newFuncFamily == LS_FAMILY_TIMER) {
@ -199,18 +188,21 @@ void LogicalSwitchesPanel::onFunctionChanged()
model->logicalSw[i].val2 = -129;
}
}
if (bool(oldFunc) != bool(newFunc))
update();
else
updateLine(i);
if (oldFunc == LS_FN_OFF || newFunc == LS_FN_OFF)
updateItemModels();
emit modified();
}
}
void LogicalSwitchesPanel::onV1Changed(int value)
{
if (!lock) {
int i = sender()->property("index").toInt();
if (model->logicalSw[i].val1 != cbSource1[i]->itemData(value).toInt()) {
model->logicalSw[i].val1 = cbSource1[i]->itemData(value).toInt();
if (model->logicalSw[i].getFunctionFamily() == LS_FAMILY_VOFS) {
if (!offsetChangedAt(i))
@ -221,24 +213,29 @@ void LogicalSwitchesPanel::onV1Changed(int value)
}
}
}
}
void LogicalSwitchesPanel::onV2Changed(int value)
{
if (!lock) {
int i = sender()->property("index").toInt();
if (model->logicalSw[i].val2 != cbSource2[i]->itemData(value).toInt()) {
model->logicalSw[i].val2 = cbSource2[i]->itemData(value).toInt();
emit modified();
}
}
}
void LogicalSwitchesPanel::onAndSwitchChanged(int value)
{
if (!lock) {
int index = sender()->property("index").toInt();
if (model->logicalSw[index].andsw != cbAndSwitch[index]->itemData(value).toInt()) {
model->logicalSw[index].andsw = cbAndSwitch[index]->itemData(value).toInt();
emit modified();
}
}
}
void LogicalSwitchesPanel::onDurationChanged(double duration)
{
@ -347,16 +344,14 @@ void LogicalSwitchesPanel::updateTimerParam(QDoubleSpinBox *sb, int timer, doubl
void LogicalSwitchesPanel::updateLine(int i)
{
const bool savelock = lock;
lock = true;
unsigned int mask;
unsigned int mask = 0;
cbFunction[i]->setCurrentIndex(cbFunction[i]->findData(model->logicalSw[i].func));
cbAndSwitch[i]->setCurrentIndex(cbAndSwitch[i]->findData(RawSwitch(model->logicalSw[i].andsw).toValue()));
if (!model->logicalSw[i].func) {
mask = 0;
}
else {
if (!model->logicalSw[i].isEmpty()) {
mask = LINE_ENABLED | DELAY_ENABLED | DURATION_ENABLED;
switch (model->logicalSw[i].getFunctionFamily())
@ -367,7 +362,7 @@ void LogicalSwitchesPanel::updateLine(int i)
RawSource source = RawSource(model->logicalSw[i].val1);
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[i].getRangeFlags());
double value = range.step * model->logicalSw[i].val2 + range.offset; /* TODO+source.getRawOffset(model)*/
cbSource1[i]->setModel(rawSourceItemModel);
cbSource1[i]->setModel(rawSourceFilteredModel);
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(source.toValue()));
if (source.isTimeBased()) {
mask |= VALUE_TO_VISIBLE;
@ -396,16 +391,16 @@ void LogicalSwitchesPanel::updateLine(int i)
case LS_FAMILY_STICKY: // no break
case LS_FAMILY_VBOOL:
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
cbSource1[i]->setModel(rawSwitchItemModel);
cbSource1[i]->setModel(rawSwitchFilteredModel);
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
cbSource2[i]->setModel(rawSwitchItemModel);
cbSource2[i]->setModel(rawSwitchFilteredModel);
cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2));
break;
case LS_FAMILY_EDGE:
mask |= SOURCE1_VISIBLE | VALUE2_VISIBLE | VALUE3_VISIBLE;
mask &= ~DELAY_ENABLED;
cbSource1[i]->setModel(rawSwitchItemModel);
cbSource1[i]->setModel(rawSwitchFilteredModel);
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
updateTimerParam(dsbOffset[i], model->logicalSw[i].val2, 0.0);
updateTimerParam(dsbOffset2[i], model->logicalSw[i].val2 + model->logicalSw[i].val3, ValToTim(TimToVal(dsbOffset[i]->value()) - 1));
@ -414,9 +409,9 @@ void LogicalSwitchesPanel::updateLine(int i)
case LS_FAMILY_VCOMP:
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
cbSource1[i]->setModel(rawSourceItemModel);
cbSource1[i]->setModel(rawSourceFilteredModel);
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
cbSource2[i]->setModel(rawSourceItemModel);
cbSource2[i]->setModel(rawSourceFilteredModel);
cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2));
break;
@ -444,7 +439,7 @@ void LogicalSwitchesPanel::updateLine(int i)
dsbDelay[i]->setValue(model->logicalSw[i].delay / 10.0);
}
lock = false;
lock = savelock;
}
void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b)
@ -484,15 +479,8 @@ void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b)
b->setMaxVisibleItems(10);
}
void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b)
{
b->setModel(rawSwitchItemModel);
b->setVisible(true);
}
void LogicalSwitchesPanel::update()
{
updateDataModels();
for (int i = 0; i < lsCapability; i++) {
updateLine(i);
}
@ -503,8 +491,8 @@ void LogicalSwitchesPanel::cmPaste()
QByteArray data;
if (hasClipboardData(&data)) {
memcpy(&model->logicalSw[selectedIndex], data.constData(), sizeof(LogicalSwitchData));
updateDataModels();
updateLine(selectedIndex);
updateItemModels();
emit modified();
}
}
@ -519,6 +507,7 @@ void LogicalSwitchesPanel::cmDelete()
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
update();
updateItemModels();
emit modified();
}
@ -539,7 +528,6 @@ void LogicalSwitchesPanel::cmCut()
cmClear(false);
}
// TODO make something generic here!
void LogicalSwitchesPanel::onCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
@ -608,7 +596,8 @@ void LogicalSwitchesPanel::cmClear(bool prompt)
model->logicalSw[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
update();
updateLine(selectedIndex);
updateItemModels();
emit modified();
}
@ -622,6 +611,7 @@ void LogicalSwitchesPanel::cmClearAll()
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, i);
}
update();
updateItemModels();
emit modified();
}
@ -631,6 +621,7 @@ void LogicalSwitchesPanel::cmInsert()
model->logicalSw[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
update();
updateItemModels();
emit modified();
}
@ -643,7 +634,30 @@ void LogicalSwitchesPanel::swapData(int idx1, int idx2)
memcpy(lsw2, lsw1, sizeof(LogicalSwitchData));
memcpy(lsw1, &lstmp, sizeof(LogicalSwitchData));
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
update();
updateLine(idx1);
updateLine(idx2);
updateItemModels();
emit modified();
}
}
void LogicalSwitchesPanel::updateItemModels()
{
lock = true;
commonItemModels->update(CommonItemModels::RMO_LOGICAL_SWITCHES);
}
void LogicalSwitchesPanel::onModelDataAboutToBeUpdated()
{
lock = true;
modelsUpdateCnt++;
}
void LogicalSwitchesPanel::onModelDataUpdateComplete()
{
modelsUpdateCnt--;
if (modelsUpdateCnt < 1) {
update();
lock = false;
}
}

View file

@ -24,8 +24,8 @@
#include "modeledit.h"
#include "radiodata.h"
class RawSwitchFilterItemModel;
class RawSourceFilterItemModel;
class CommonItemModels;
class RawItemFilteredModel;
class TimerEdit;
constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch";
@ -35,13 +35,12 @@ class LogicalSwitchesPanel : public ModelPanel
Q_OBJECT
public:
LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~LogicalSwitchesPanel();
virtual void update();
private slots:
void updateDataModels();
void onFunctionChanged();
void onV1Changed(int value);
void onV2Changed(int value);
@ -61,6 +60,8 @@ class LogicalSwitchesPanel : public ModelPanel
void cmInsert();
void cmClear(bool prompt = true);
void cmClearAll();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES];
@ -73,11 +74,11 @@ class LogicalSwitchesPanel : public ModelPanel
QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES];
QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES];
QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES];
RawSwitchFilterItemModel * rawSwitchItemModel;
RawSourceFilterItemModel * rawSourceItemModel;
CommonItemModels * commonItemModels;
RawItemFilteredModel * rawSwitchFilteredModel;
RawItemFilteredModel * rawSourceFilteredModel;
int selectedIndex;
void populateFunctionCB(QComboBox *b);
void populateAndSwitchCB(QComboBox *b);
void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0);
int lsCapability;
int lsCapabilityExt;
@ -86,6 +87,8 @@ class LogicalSwitchesPanel : public ModelPanel
bool insertAllowed() const;
bool moveDownAllowed() const;
bool moveUpAllowed() const;
int modelsUpdateCnt;
void updateItemModels();
};
#endif // _LOGICALSWITCHES_H_

View file

@ -24,7 +24,8 @@
#include "rawitemfilteredmodel.h"
#include "helpers.h"
MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware) :
MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware,
RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) :
QDialog(parent),
ui(new Ui::MixerDialog),
model(model),
@ -34,6 +35,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
lock(false)
{
ui->setupUi(this);
QRegExp rx(CHAR_FOR_NAMES_REGEX);
QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 };
QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 };
@ -43,16 +45,14 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh - 1).toString(&model, &generalSettings)));
ui->sourceCB->setModel(new RawSourceFilterItemModel(&generalSettings, &model, RawSource::InputSourceGroups | RawSource::ScriptsGroup, this));
ui->sourceCB->setModel(rawSourceModel);
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue()));
ui->sourceCB->removeItem(0);
int limit = firmware->getCapability(OffsetWeight);
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);
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB,
md->curve, model, firmware->getCapability(HasMixerExpo) ? 0 : HIDE_EXPO);
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, curveItemModel, this);
ui->MixDR_CB->setChecked(md->noExpo == 0);
@ -104,7 +104,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
}
}
ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this));
ui->switchesCB->setModel(rawSwitchModel);
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue()));
ui->warningCB->setCurrentIndex(md->mixWarn);
ui->mltpxCB->setCurrentIndex(md->mltpx);
@ -147,10 +147,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
MixerDialog::~MixerDialog()
{
delete ui;
delete gvWeightGroup;
delete gvOffsetGroup;
delete curveGroup;
delete ui;
}
void MixerDialog::changeEvent(QEvent *e)

View file

@ -25,7 +25,8 @@
#include "eeprominterface.h"
class GVarGroup;
class CurveGroup;
class RawItemFilteredModel;
class CurveReferenceUIManager;
namespace Ui {
class MixerDialog;
@ -34,7 +35,8 @@ namespace Ui {
class MixerDialog : public QDialog {
Q_OBJECT
public:
MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware);
MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware,
RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel);
~MixerDialog();
protected:
@ -57,7 +59,7 @@ class MixerDialog : public QDialog {
bool lock;
GVarGroup * gvWeightGroup;
GVarGroup * gvOffsetGroup;
CurveGroup * curveGroup;
CurveReferenceUIManager * curveGroup;
QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES];
};

View file

@ -20,13 +20,27 @@
#include "mixes.h"
#include "helpers.h"
#include "rawitemfilteredmodel.h"
MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
mixInserted(false),
highlightedSource(0),
modelPrinter(firmware, generalSettings, model)
modelPrinter(firmware, generalSettings, model),
commonItemModels(commonItemModels)
{
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), ((RawSource::InputSourceGroups | RawSource::ScriptsGroup) & ~ RawSource::NoneGroup), this);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete);
curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this);
connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated);
connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete);
QGridLayout * mixesLayout = new QGridLayout(this);
mixersListWidget = new MixersListWidget(this, false); // TODO enum
@ -175,8 +189,8 @@ void MixesPanel::gm_openMix(int index)
MixData mixd(model->mixData[index]);
MixerDialog *g = new MixerDialog(this, *model, &mixd, generalSettings, firmware);
if(g->exec()) {
MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel);
if(dlg->exec()) {
model->mixData[index] = mixd;
emit modified();
update();
@ -188,6 +202,7 @@ void MixesPanel::gm_openMix(int index)
mixInserted = false;
update();
}
delete dlg;
}
int MixesPanel::getMixerIndex(unsigned int dch)
@ -529,3 +544,14 @@ void MixesPanel::clearMixes()
update();
}
}
void MixesPanel::onModelDataAboutToBeUpdated()
{
lock = true;
}
void MixesPanel::onModelDataUpdateComplete()
{
update();
lock = false;
}

View file

@ -26,12 +26,15 @@
#include "mixerdialog.h"
#include "modelprinter.h"
class CommonItemModels;
class RawItemFilteredModel;
class MixesPanel : public ModelPanel
{
Q_OBJECT
public:
MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~MixesPanel();
virtual void update();
@ -50,7 +53,6 @@ class MixesPanel : public ModelPanel
void moveMixDown();
void mixerHighlight();
void mixerlistWidget_customContextMenuRequested(QPoint pos);
void mixerlistWidget_doubleClicked(QModelIndex index);
void mixerlistWidget_KeyPress(QKeyEvent *event);
@ -58,11 +60,18 @@ class MixesPanel : public ModelPanel
void mimeMixerDropped(int index, const QMimeData *data, Qt::DropAction action);
void pasteMixerMimeData(const QMimeData * mimeData, int destIdx);
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
MixersListWidget * mixersListWidget;
bool mixInserted;
unsigned int highlightedSource;
ModelPrinter modelPrinter;
CommonItemModels * commonItemModels;
RawItemFilteredModel *rawSourceFilteredModel;
RawItemFilteredModel *rawSwitchFilteredModel;
RawItemFilteredModel *curveFilteredModel;
int getMixerIndex(unsigned int dch);
bool gm_insertMix(int idx);

View file

@ -33,6 +33,7 @@
#include "customfunctions.h"
#include "telemetry.h"
#include "appdata.h"
#include "rawitemdatamodels.h"
ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmware * firmware) :
QDialog(parent),
@ -48,33 +49,55 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw
setWindowIcon(CompanionIcon("edit.png"));
restoreGeometry(g.modelEditGeo());
ui->pushButton->setIcon(CompanionIcon("simulate.png"));
SetupPanel * setupPanel = new SetupPanel(this, radioData.models[modelId], radioData.generalSettings, firmware);
GeneralSettings &generalSettings = radioData.generalSettings;
ModelData &model = radioData.models[modelId];
commonItemModels = new CommonItemModels(&generalSettings, &model, this);
s1.report("Init");
SetupPanel * setupPanel = new SetupPanel(this, model, generalSettings, firmware, commonItemModels);
addTab(setupPanel, tr("Setup"));
if (firmware->getCapability(Heli))
addTab(new HeliPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Heli"));
addTab(new FlightModesPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Flight Modes"));
addTab(new InputsPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Inputs"));
s1.report("inputs");
addTab(new MixesPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Mixes"));
s1.report("Setup");
if (firmware->getCapability(Heli)) {
addTab(new HeliPanel(this, model, generalSettings, firmware, commonItemModels), tr("Heli"));
s1.report("Heli");
}
addTab(new FlightModesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Flight Modes"));
s1.report("Flight Modes");
addTab(new InputsPanel(this, model, generalSettings, firmware, commonItemModels), tr("Inputs"));
s1.report("Inputs");
addTab(new MixesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Mixes"));
s1.report("Mixes");
Channels * chnPanel = new Channels(this, radioData.models[modelId], radioData.generalSettings, firmware);
addTab(chnPanel, tr("Outputs"));
ChannelsPanel * channelsPanel = new ChannelsPanel(this, model, generalSettings, firmware, commonItemModels);
addTab(channelsPanel, tr("Outputs"));
s1.report("Outputs");
addTab(new Curves(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Curves"));
addTab(new LogicalSwitchesPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Logical Switches"));
s1.report("LS");
addTab(new CustomFunctionsPanel(this, &radioData.models[modelId], radioData.generalSettings, firmware), tr("Special Functions"));
s1.report("CF");
if (firmware->getCapability(Telemetry))
addTab(new TelemetryPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Telemetry"));
onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel
addTab(new CurvesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Curves"));
s1.report("Curves");
connect(setupPanel, &SetupPanel::extendedLimitsToggled, chnPanel, &Channels::refreshExtendedLimits);
addTab(new LogicalSwitchesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Logical Switches"));
s1.report("Logical Switches");
addTab(new CustomFunctionsPanel(this, &model, generalSettings, firmware, commonItemModels), tr("Special Functions"));
s1.report("Special Functions");
if (firmware->getCapability(Telemetry)) {
addTab(new TelemetryPanel(this, model, generalSettings, firmware, commonItemModels), tr("Telemetry"));
s1.report("Telemetry");
}
connect(setupPanel, &SetupPanel::extendedLimitsToggled, channelsPanel, &ChannelsPanel::refreshExtendedLimits);
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &ModelEdit::onTabIndexChanged);
connect(ui->pushButton, &QPushButton::clicked, this, &ModelEdit::launchSimulation);
s1.report("end");
onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel
gStopwatch.report("ModelEdit end constructor");
}

View file

@ -25,6 +25,7 @@
#include "genericpanel.h"
class RadioData;
class CommonItemModels;
namespace Ui {
class ModelEdit;
@ -62,6 +63,7 @@ class ModelEdit : public QDialog
RadioData & radioData;
Firmware * firmware;
QVector<GenericPanel *> panels;
CommonItemModels * commonItemModels;
void addTab(GenericPanel *panel, QString text);
void launchSimulation();

View file

@ -31,13 +31,14 @@
#include <QDir>
TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, RawSwitchFilterItemModel * switchModel):
TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, RawItemFilteredModel * rawSwitchFilteredModel):
ModelPanel(parent, model, generalSettings, firmware),
timer(timer),
ui(new Ui::Timer)
{
ui->setupUi(this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TimerPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &TimerPanel::onModelDataUpdateComplete);
lock = true;
@ -48,11 +49,10 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
}
else {
ui->name->setMaxLength(length);
//ui->name->setText(timer.name);
}
// Mode
ui->mode->setModel(switchModel);
ui->mode->setModel(rawSwitchFilteredModel);
ui->mode->setCurrentIndex(ui->mode->findData(timer.mode.toValue()));
connect(ui->mode, SIGNAL(activated(int)), this, SLOT(onModeChanged(int)));
@ -94,6 +94,7 @@ TimerPanel::~TimerPanel()
void TimerPanel::update()
{
lock = true;
ui->name->setText(timer.name);
int hour = timer.val / 3600;
@ -165,11 +166,23 @@ void TimerPanel::on_name_editingFinished()
if (QString(timer.name) != ui->name->text()) {
int length = ui->name->maxLength();
strncpy(timer.name, ui->name->text().toLatin1(), length);
emit nameChanged();
emit modified();
}
}
}
void TimerPanel::onModelDataAboutToBeUpdated()
{
lock = true;
}
void TimerPanel::onModelDataUpdateComplete()
{
update();
lock = false;
}
/******************************************************************************/
#define FAILSAFE_CHANNEL_HOLD 2000
@ -703,8 +716,8 @@ void ModulePanel::on_channelsCount_editingFinished()
{
if (!lock && module.channelsCount != ui->channelsCount->value()) {
module.channelsCount = ui->channelsCount->value();
update();
emit channelsRangeChanged();
update();
emit modified();
}
}
@ -713,8 +726,8 @@ void ModulePanel::on_channelsStart_editingFinished()
{
if (!lock && module.channelsStart != (unsigned)ui->channelsStart->value() - 1) {
module.channelsStart = (unsigned)ui->channelsStart->value() - 1;
update();
emit channelsRangeChanged();
update();
emit modified();
}
}
@ -978,18 +991,20 @@ void ModulePanel::onClearAccessRxClicked()
/******************************************************************************/
SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::Setup)
ui(new Ui::Setup),
commonItemModels(commonItemModels)
{
ui->setupUi(this);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::TimersContext, this);
Board::Type board = firmware->getBoard();
lock = true;
memset(modules, 0, sizeof(modules));
ui->setupUi(this);
QRegExp rx(CHAR_FOR_NAMES_REGEX);
ui->name->setValidator(new QRegExpValidator(rx, this));
ui->name->setMaxLength(firmware->getCapability(ModelName));
@ -1062,18 +1077,16 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
}
QWidget * prevFocus = ui->image;
RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this);
connect(this, &SetupPanel::updated, swModel, &RawSwitchFilterItemModel::update);
timersCount = firmware->getCapability(Timers);
for (int i = 0; i < CPN_MAX_TIMERS; i++) {
if (i < timersCount) {
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, swModel);
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, rawSwitchFilteredModel);
ui->gridLayout->addWidget(timers[i], 1+i, 1);
connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
connect(timers[i], &TimerPanel::nameChanged, this, &SetupPanel::onTimerNameChanged);
connect(this, &SetupPanel::updated, timers[i], &TimerPanel::update);
connect(this, &SetupPanel::timerUpdated, timers[i], &TimerPanel::update);
prevFocus = timers[i]->getLastFocus();
// TODO more reliable method required
QLabel *label = findChild<QLabel *>(QString("label_timer%1").arg(i + 1));
@ -1362,9 +1375,15 @@ void SetupPanel::populateThrottleTrimSwitchCB()
lock = true;
ui->throttleTrimSwitch->clear();
int idx=0;
QString trim;
for (int i=0; i<getBoardCapability(board, Board::NumTrims); i++, idx++) {
QString trim = RawSource(SOURCE_TYPE_TRIM, i).toString(model, &generalSettings);
trim = (trim == "TrmR") ? "TrmT" : (trim == "TmrT") ? "TmrR" : trim;
// here order is TERA instead of RETA
if (i == 0)
trim = RawSource(SOURCE_TYPE_TRIM, 2).toString(model, &generalSettings);
else if (i == 2)
trim = RawSource(SOURCE_TYPE_TRIM, 0).toString(model, &generalSettings);
else
trim = RawSource(SOURCE_TYPE_TRIM, i).toString(model, &generalSettings);
ui->throttleTrimSwitch->addItem(trim, idx);
}
@ -1627,7 +1646,7 @@ void SetupPanel::cmTimerClear(bool prompt)
model->timers[selectedTimerIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex);
emit timerUpdated();
updateItemModels();
emit modified();
}
@ -1640,7 +1659,7 @@ void SetupPanel::cmTimerClearAll()
model->timers[i].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, i);
}
emit timerUpdated();
updateItemModels();
emit modified();
}
@ -1674,7 +1693,7 @@ void SetupPanel::cmTimerDelete()
}
model->timers[maxidx].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, -1);
emit timerUpdated();
updateItemModels();
emit modified();
}
@ -1687,7 +1706,7 @@ void SetupPanel::cmTimerInsert()
}
model->timers[selectedTimerIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, 1);
emit timerUpdated();
updateItemModels();
emit modified();
}
@ -1707,7 +1726,7 @@ void SetupPanel::cmTimerPaste()
if (hasTimerClipboardData(&data)) {
TimerData *td = &model->timers[selectedTimerIndex];
memcpy(td, data.constData(), sizeof(TimerData));
emit timerUpdated();
updateItemModels();
emit modified();
}
}
@ -1721,7 +1740,17 @@ void SetupPanel::swapTimerData(int idx1, int idx2)
memcpy(td2, td1, sizeof(TimerData));
memcpy(td1, &tdtmp, sizeof(TimerData));
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
emit timerUpdated();
updateItemModels();
emit modified();
}
}
void SetupPanel::onTimerNameChanged()
{
updateItemModels();
}
void SetupPanel::updateItemModels()
{
commonItemModels->update(CommonItemModels::RMO_TIMERS);
}

View file

@ -26,7 +26,8 @@
constexpr char MIMETYPE_TIMER[] = "application/x-companion-timer";
class RawSwitchFilterItemModel;
class CommonItemModels;
class RawItemFilteredModel;
namespace Ui {
class Setup;
@ -39,7 +40,7 @@ class TimerPanel : public ModelPanel
Q_OBJECT
public:
TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget *prevFocus, RawSwitchFilterItemModel * switchModel);
TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget *prevFocus, RawItemFilteredModel * switchModel);
virtual ~TimerPanel();
virtual void update();
@ -50,6 +51,11 @@ class TimerPanel : public ModelPanel
void on_value_editingFinished();
void on_minuteBeep_toggled(bool checked);
void on_name_editingFinished();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
signals:
void nameChanged();
private:
TimerData & timer;
@ -125,7 +131,7 @@ class SetupPanel : public ModelPanel
Q_OBJECT
public:
SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~SetupPanel();
virtual void update();
@ -133,7 +139,6 @@ class SetupPanel : public ModelPanel
signals:
void extendedLimitsToggled();
void updated();
void timerUpdated();
private slots:
void on_name_editingFinished();
@ -164,6 +169,7 @@ class SetupPanel : public ModelPanel
void cmTimerPaste();
void cmTimerMoveDown();
void cmTimerMoveUp();
void onTimerNameChanged();
private:
Ui::Setup *ui;
@ -185,6 +191,9 @@ class SetupPanel : public ModelPanel
bool moveTimerDownAllowed() const;
bool moveTimerUpAllowed() const;
void swapTimerData(int idx1, int idx2);
CommonItemModels * commonItemModels;
RawItemFilteredModel * rawSwitchFilteredModel;
void updateItemModels();
};
#endif // _SETUP_H_

View file

@ -28,18 +28,20 @@
#include <TimerEdit>
TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel):
TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetryCustomScreen),
screen(screen)
{
ui->setupUi(this);
connect(rawSourceModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TelemetryCustomScreen::onModelDataAboutToBeUpdated);
connect(rawSourceModel, &RawItemFilteredModel::dataUpdateComplete, this, &TelemetryCustomScreen::onModelDataUpdateComplete);
for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) {
for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) {
fieldsCB[l][c] = new QComboBox(this);
fieldsCB[l][c]->setProperty("index", c + (l << 8));
fieldsCB[l][c]->setModel(srcModel);
fieldsCB[l][c]->setModel(rawSourceModel);
ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1);
connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int)));
}
@ -48,7 +50,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) {
barsCB[l] = new QComboBox(this);
barsCB[l]->setProperty("index", l);
barsCB[l]->setModel(srcModel);
barsCB[l]->setModel(rawSourceModel);
connect(barsCB[l], SIGNAL(activated(int)), this, SLOT(barSourceChanged(int)));
ui->screenBarsLayout->addWidget(barsCB[l], l, 0, 1, 1);
@ -287,6 +289,17 @@ void TelemetryCustomScreen::barTimeChanged()
}
}
void TelemetryCustomScreen::onModelDataAboutToBeUpdated()
{
lock = true;
}
void TelemetryCustomScreen::onModelDataUpdateComplete()
{
update();
lock = false;
}
/******************************************************/
TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
@ -305,6 +318,7 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor,
QFontMetrics *f = new QFontMetrics(QFont());
QSize sz;
sz = f->size(Qt::TextSingleLine, "TELE00");
delete f;
ui->numLabel->setMinimumWidth(sz.width());
ui->numLabel->setContextMenuPolicy(Qt::CustomContextMenu);
ui->numLabel->setToolTip(tr("Popup menu available"));
@ -505,7 +519,6 @@ void TelemetrySensorPanel::on_name_editingFinished()
if (!lock) {
strcpy(sensor.label, ui->name->text().toLatin1());
emit dataModified();
emit modified();
}
}
@ -535,7 +548,6 @@ void TelemetrySensorPanel::on_formula_currentIndexChanged(int index)
sensor.unit = SensorData::UNIT_METERS;
}
emit dataModified();
emit modified();
}
}
@ -631,7 +643,6 @@ void TelemetrySensorPanel::cmPaste()
if (hasClipboardData(&data)) {
memcpy(&sensor, data.constData(), sizeof(SensorData));
emit dataModified();
emit modified();
}
}
@ -645,7 +656,6 @@ void TelemetrySensorPanel::cmClear(bool prompt)
sensor.clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
emit dataModified();
emit modified();
}
void TelemetrySensorPanel::cmClearAll()
@ -678,11 +688,13 @@ void TelemetrySensorPanel::cmMoveDown()
/******************************************************/
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::Telemetry)
ui(new Ui::Telemetry),
commonItemModels(commonItemModels)
{
ui->setupUi(this);
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this);
sensorCapability = firmware->getCapability(Sensors);
if (sensorCapability > CPN_MAX_SENSORS) // TODO should be role of getCapability
@ -696,11 +708,12 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
ui->A1GB->hide();
ui->A2GB->hide();
for (int i = 0; i < sensorCapability; ++i) {
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, firmware);
ui->sensorsLayout->addWidget(panel);
sensorPanels[i] = panel;
connect(panel, SIGNAL(dataModified()), this, SLOT(update()));
connect(panel, SIGNAL(dataModified()), this, SLOT(on_dataModifiedSensor()));
connect(panel, SIGNAL(modified()), this, SLOT(onModified()));
connect(panel, SIGNAL(clearAllSensors()), this, SLOT(on_clearAllSensors()));
connect(panel, SIGNAL(insertSensor(int)), this, SLOT(on_insertSensor(int)));
@ -717,15 +730,11 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
ui->topbarGB->hide();
}
RawSourceFilterItemModel * srcModel = (new RawSourceFilterItemModel(&generalSettings, &model, this));
connect(this, &TelemetryPanel::updated, srcModel, &RawSourceFilterItemModel::update);
for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) {
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel);
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, rawSourceFilteredModel);
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i + 1));
telemetryCustomScreens[i] = tab;
connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified);
connect(this, &TelemetryPanel::updated, tab, &TelemetryCustomScreen::update);
}
disableMouseScrolling();
@ -759,13 +768,13 @@ void TelemetryPanel::update()
sensorPanels[i]->update();
}
emit updated();
for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) {
telemetryCustomScreens[i]->update();
}
}
void TelemetryPanel::setup()
{
QString firmware_id = g.profile[g.id()].fwType();
lock = true;
ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0);
@ -792,8 +801,7 @@ void TelemetryPanel::setup()
ui->rssiAlarmWarningLabel->setText(tr("Low Alarm"));
ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm"));
int varioCap = firmware->getCapability(HasVario);
if (!varioCap) {
if (!firmware->getCapability(HasVario)) {
ui->varioLimitMax_DSB->hide();
ui->varioLimitMin_DSB->hide();
ui->varioLimitCenterMin_DSB->hide();
@ -972,6 +980,7 @@ void TelemetryPanel::on_clearAllSensors()
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, i);
}
updateItemModels();
update();
emit modified();
}
@ -982,6 +991,7 @@ void TelemetryPanel::on_insertSensor(int selectedIndex)
model->sensorData[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
updateItemModels();
update();
emit modified();
}
@ -995,6 +1005,7 @@ void TelemetryPanel::on_deleteSensor(int selectedIndex)
model->sensorData[CPN_MAX_SENSORS - 1].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
updateItemModels();
update();
emit modified();
}
@ -1018,7 +1029,20 @@ void TelemetryPanel::swapData(int idx1, int idx2)
memcpy(sd2, sd1, sizeof(SensorData));
memcpy(sd1, &sdtmp, sizeof(SensorData));
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
updateItemModels();
update();
emit modified();
}
}
void TelemetryPanel::on_dataModifiedSensor()
{
updateItemModels();
update();
emit modified();
}
void TelemetryPanel::updateItemModels()
{
commonItemModels->update(CommonItemModels::RMO_TELEMETRY_SENSORS);
}

View file

@ -27,7 +27,8 @@
constexpr char MIMETYPE_TELE_SENSOR[] = "application/x-companion-tele-sensor";
class AutoComboBox;
class RawSourceFilterItemModel;
class CommonItemModels;
class RawItemFilteredModel;
class TimerEdit;
namespace Ui {
@ -41,7 +42,7 @@ class TelemetryCustomScreen: public ModelPanel
Q_OBJECT
public:
TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel);
TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel);
~TelemetryCustomScreen();
void update();
@ -53,6 +54,8 @@ class TelemetryCustomScreen: public ModelPanel
void barMinChanged(double value);
void barMaxChanged(double value);
void barTimeChanged();
void onModelDataAboutToBeUpdated();
void onModelDataUpdateComplete();
private:
void updateBar(int line);
@ -122,7 +125,7 @@ class TelemetryPanel : public ModelPanel
Q_OBJECT
public:
TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels);
virtual ~TelemetryPanel();
virtual void update();
@ -148,12 +151,15 @@ class TelemetryPanel : public ModelPanel
void on_deleteSensor(int index);
void on_moveUpSensor(int index);
void on_moveDownSensor(int index);
void on_dataModifiedSensor();
private:
Ui::Telemetry *ui;
TelemetryCustomScreen * telemetryCustomScreens[4];
TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS];
int sensorCapability;
CommonItemModels * commonItemModels;
RawItemFilteredModel * rawSourceFilteredModel;
void setup();
void telBarUpdate();
@ -161,6 +167,7 @@ class TelemetryPanel : public ModelPanel
void populateCurrentSource();
void populateVarioSource();
void swapData(int idx1, int idx2);
void updateItemModels();
};
#endif // _TELEMETRY_H_

View file

@ -24,6 +24,7 @@
#include "boards.h"
#include "helpers_html.h"
#include "appdata.h"
#include "adjustmentreference.h"
#include <QApplication>
#include <QPainter>
@ -396,7 +397,7 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
str += input.srcRaw.toString(&model, &generalSettings).toHtmlEscaped();
}
str += " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(Helpers::getAdjustmentString(input.weight, &model, true).toHtmlEscaped());
str += " " + tr("Weight(%1)").arg(AdjustmentReference(input.weight).toString(&model, true)).toHtmlEscaped();
if (input.curve.value)
str += " " + input.curve.toString(&model).toHtmlEscaped();
@ -405,19 +406,18 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
str += " " + flightModesStr.toHtmlEscaped();
if (input.swtch.type != SWITCH_TYPE_NONE)
str += " " + tr("Switch").toHtmlEscaped() + QString("(%1)").arg(input.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped();
str += " " + tr("Switch(%1)").arg(input.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped();
if (firmware->getCapability(VirtualInputs)) {
if (input.carryTrim > 0)
str += " " + tr("NoTrim").toHtmlEscaped();
str += " " + tr("NoTrim");
else if (input.carryTrim < 0)
str += " " + RawSource(SOURCE_TYPE_TRIM, (-(input.carryTrim) - 1)).toString(&model, &generalSettings).toHtmlEscaped();
}
if (input.offset)
str += " " + tr("Offset(%1)").arg(Helpers::getAdjustmentString(input.offset, &model)).toHtmlEscaped();
str += " " + tr("Offset(%1)").arg(AdjustmentReference(input.offset).toString(&model)).toHtmlEscaped();
if (firmware->getCapability(HasExpoNames) && input.name[0])
str += QString(" [%1]").arg(input.name).toHtmlEscaped();
@ -448,35 +448,35 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
if (mix.mltpx == MLTPX_MUL && !showMultiplex)
str += " " + tr("MULT!").toHtmlEscaped();
else
str += " " + tr("Weight") + QString("(%1)").arg(Helpers::getAdjustmentString(mix.weight, &model, true)).toHtmlEscaped();
str += " " + tr("Weight(%1)").arg(AdjustmentReference(mix.weight).toString(&model, true)).toHtmlEscaped();
QString flightModesStr = printFlightModes(mix.flightModes);
if (!flightModesStr.isEmpty())
str += " " + flightModesStr.toHtmlEscaped();
if (mix.swtch.type != SWITCH_TYPE_NONE)
str += " " + tr("Switch") + QString("(%1)").arg(mix.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped();
str += " " + tr("Switch(%1)").arg(mix.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped();
if (mix.carryTrim > 0)
str += " " + tr("NoTrim").toHtmlEscaped();
str += " " + tr("NoTrim");
else if (mix.carryTrim < 0)
str += " " + RawSource(SOURCE_TYPE_TRIM, (-(mix.carryTrim)-1)).toString(&model, &generalSettings);
if (firmware->getCapability(HasNoExpo) && mix.noExpo)
str += " " + tr("No DR/Expo").toHtmlEscaped();
if (mix.sOffset)
str += " " + tr("Offset") + QString("(%1)").arg(Helpers::getAdjustmentString(mix.sOffset, &model)).toHtmlEscaped();
str += " " + tr("Offset(%1)").arg(AdjustmentReference(mix.sOffset).toString(&model)).toHtmlEscaped();
if (mix.curve.value)
str += " " + mix.curve.toString(&model).toHtmlEscaped();
int scale = firmware->getCapability(SlowScale);
if (scale == 0)
scale = 1;
if (mix.delayDown || mix.delayUp)
str += " " + tr("Delay") + QString("(u%1:d%2)").arg((double)mix.delayUp/scale).arg((double)mix.delayDown/scale).toHtmlEscaped();
str += " " + tr("Delay(u%1:d%2)").arg((double)mix.delayUp / scale).arg((double)mix.delayDown / scale).toHtmlEscaped();
if (mix.speedDown || mix.speedUp)
str += " " + tr("Slow") + QString("(u%1:d%2)").arg((double)mix.speedUp/scale).arg((double)mix.speedDown/scale).toHtmlEscaped();
str += " " + tr("Slow(u%1:d%2)").arg((double)mix.speedUp / scale).arg((double)mix.speedDown / scale).toHtmlEscaped();
if (mix.mixWarn)
str += " " + tr("Warn") + QString("(%1)").arg(mix.mixWarn).toHtmlEscaped();
str += " " + tr("Warn(%1)").arg(mix.mixWarn).toHtmlEscaped();
if (firmware->getCapability(HasMixerNames) && mix.name[0])
str += QString(" [%1]").arg(mix.name).toHtmlEscaped();
return str;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,11 @@ local function run(event)
return 2
end
if crossfireTelemetryPush() == nil then
error("Crossfire not available!")
return 2
end
chdir("/SCRIPTS/TOOLS/CROSSFIRE")
return "crossfire.lua"
end

View file

@ -30,6 +30,11 @@ local function run(event)
return 2
end
if crossfireTelemetryPush() == nil then
error("Crossfire not available!")
return 2
end
chdir("/SCRIPTS/TOOLS/CROSSFIRE")
return "crossfire.lua"
end

View file

@ -171,6 +171,8 @@ local function init()
local ver, radio, maj, minor, rev = getVersion()
if string.match(radio, "x7") then
switches = {"SA", "SB", "SC", "SD", "SF", "SH"}
elseif string.match(radio, "tx12") then
switches = {"SA", "SB", "SC", "SD", "SE", "SF"}
else
switches = {"SA", "SB", "SC", "SD"}
end

View file

@ -30,6 +30,11 @@ local function run(event)
return 2
end
if crossfireTelemetryPush() == nil then
error("Crossfire not available!")
return 2
end
chdir("/SCRIPTS/TOOLS/CROSSFIRE")
return "crossfire.lua"
end

View file

@ -36,7 +36,6 @@
#define HEADER_LINE_COLUMNS 0,
#endif
#define COLUMN_X 0
#define drawFieldLabel(x, y, str) lcdDrawTextAlignedLeft(y, str)
#define NUM_BODY_LINES (LCD_LINES-1)

View file

@ -83,7 +83,7 @@ void onModelSelectMenu(const char * result)
void menuModelSelect(event_t event)
{
event_t _event_ = event;
if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT) || IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event)) {
if ((s_copyMode && IS_KEY_EVT(event, KEY_EXIT)) || event == EVT_KEY_BREAK(KEY_EXIT) || IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event)) {
_event_ = 0;
}

View file

@ -276,10 +276,12 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
}
#endif // OVERRIDE_CHANNEL_FUNCTION
else if (func >= FUNC_SET_FAILSAFE && func <= FUNC_BIND) {
#if defined(DANGEROUS_MODULE_FUNCTIONS)
else if (func >= FUNC_RANGECHECK && func <= FUNC_BIND) {
val_max = NUM_MODULES-1;
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, "\004Int.Ext.", CFN_PARAM(cfn), attr);
}
#endif
else if (func == FUNC_SET_TIMER) {
getMixSrcRange(MIXSRC_FIRST_TIMER, val_min, val_max);
drawTimer(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT, attr);

View file

@ -44,7 +44,6 @@ struct {
#define PHASE_FLAGS 0
#define VBATT_X (6*FW-1)
#define VBATT_Y (2*FH)
#define VBATTUNIT_X (VBATT_X-1)
#define VBATTUNIT_Y (3*FH)
#define REBOOT_X (20*FW-3)
#define BAR_HEIGHT (BOX_WIDTH-1l) // don't remove the l here to force 16bits maths on 9X
@ -260,8 +259,13 @@ void displayBattVoltage()
count = (get_tmr10ms() & 127u) * count / 128;
}
#endif
for (uint8_t i = 0; i < count; i += 2)
for (uint8_t i = 0; i < count; i += 2) {
#if defined(USB_CHARGER)
if ((i >= count - 2) && usbChargerLed() && BLINK_ON_PHASE) // Blink last segment on charge
continue;
#endif
lcdDrawSolidVerticalLine(VBATT_X - 24 + i, VBATT_Y + 10, 3);
}
if (!IS_TXBATT_WARNING() || BLINK_ON_PHASE)
lcdDrawSolidFilledRect(VBATT_X - 26, VBATT_Y, 24, 15);
#else

View file

@ -268,10 +268,12 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
}
#endif
else if (func >= FUNC_SET_FAILSAFE && func <= FUNC_BIND) {
#if defined(DANGEROUS_MODULE_FUNCTIONS)
else if (func >= FUNC_RANGECHECK && func <= FUNC_BIND) {
val_max = NUM_MODULES-1;
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, "\004Int.Ext.", CFN_PARAM(cfn), attr);
}
#endif
else if (func == FUNC_SET_TIMER) {
getMixSrcRange(MIXSRC_FIRST_TIMER, val_min, val_max);
drawTimer(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT|TIMEHOUR, attr);

View file

@ -27,7 +27,6 @@
#define MODELNAME_Y (11)
#define VBATT_X (MODELNAME_X+26)
#define VBATT_Y (FH+3)
#define VBATTUNIT_X (VBATT_X-2)
#define VBATTUNIT_Y VBATT_Y
#define BITMAP_X ((LCD_W-64)/2)
#define BITMAP_Y (LCD_H/2)

View file

@ -1,105 +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.
*/
#include "opentx.h"
#include "sliders.h"
#include "trims.h"
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
#define HAS_SLIDERS() (persistentData->options[2].value.boolValue == true)
#define HAS_TRIMS() (persistentData->options[3].value.boolValue == true)
#define IS_MIRRORED() (persistentData->options[4].value.boolValue == true)
const uint8_t LBM_LAYOUT_4P2[] = {
#include "mask_layout4+2.lbm"
};
const ZoneOption OPTIONS_LAYOUT_4P2[] = {
{ STR_TOP_BAR, ZoneOption::Bool },
{ STR_FLIGHT_MODE, ZoneOption::Bool },
{ STR_SLIDERS, ZoneOption::Bool },
{ STR_TRIMS, ZoneOption::Bool },
{ STR_MIRROR, ZoneOption::Bool },
{ nullptr, ZoneOption::Bool }
};
class Layout4P2: public Layout
{
public:
Layout4P2(const LayoutFactory * factory, Layout::PersistentData * persistentData):
Layout(factory, persistentData)
{
decorate();
}
void create() override
{
Layout::create();
persistentData->options[0].value.boolValue = true;
persistentData->options[1].value.boolValue = true;
persistentData->options[2].value.boolValue = true;
persistentData->options[3].value.boolValue = true;
persistentData->options[4].value.boolValue = false;
persistentData->options[5].value.boolValue = false;
decorate();
}
void decorate()
{
Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM());
}
unsigned int getZonesCount() const override
{
return 6;
}
rect_t getZone(unsigned int index) const override
{
coord_t areaw = LCD_W - (HAS_SLIDERS() ? 2 * TRIM_SQUARE_SIZE : 0) - (HAS_TRIMS() ? 2 * TRIM_SQUARE_SIZE : 0) - 10;
coord_t areah = LCD_H - (HAS_TOPBAR() ? TOPBAR_HEIGHT : 0) - (HAS_SLIDERS() ? TRIM_SQUARE_SIZE : 0) - (HAS_TRIMS() ? TRIM_SQUARE_SIZE : 0) - 10;
areah = 4 * (areah % 4);
return {
IS_MIRRORED() ? ((index >= 4) ? (LCD_W - areaw) / 2 : 240) : ((index >= 4) ? 240 : (LCD_W - areaw) / 2),
static_cast<coord_t>((index >= 4) ? (HAS_TOPBAR() ? TOPBAR_HEIGHT + 1 : 1) + (index == 5 ? areah / 4 : 0) : (HAS_TOPBAR() ? TOPBAR_HEIGHT + 1 : 1) + (index % 4) * (areah / 4)),
areaw / 2,
(index >= 4) ? (areah / 2) : (areah / 4)
};
}
void checkEvents() override
{
Layout::checkEvents();
uint8_t newValue = persistentData->options[4].value.boolValue << 4 | persistentData->options[3].value.boolValue << 3 | persistentData->options[2].value.boolValue << 2
| persistentData->options[1].value.boolValue << 1 | persistentData->options[0].value.boolValue;
if (value != newValue) {
value = newValue;
// TODO call this from the Layout config window
this->clear();
decorate();
}
}
protected:
uint8_t value = 0;
};
BaseLayoutFactory<Layout4P2> layout4P2("Layout4P2", "4 + 2", LBM_LAYOUT_4P2, OPTIONS_LAYOUT_4P2);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -614,6 +614,7 @@ bool menuScreenSetup(int index, event_t event)
ZoneOptionValue * value = currentScreen->getOptionValue(o);
if (editZoneOption(y, option, value, attr, EE_MODEL, event)) {
currentScreen->update();
loadCustomScreens();
}
}
else if (menuPageCount > 3 && o == optionsCount) {

View file

@ -64,6 +64,11 @@ void TopBar::paint(BitmapBuffer * dc)
dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, MENU_COLOR);
}
// Logs
if (isFunctionActive(FUNCTION_LOGS) && !usbPlugged() && BLINK_ON_PHASE) {
dc->drawBitmapPattern(LCD_W - 98, 6, LBM_DOT, MENU_COLOR);
}
// RSSI
const uint8_t rssiBarsValue[] = {30, 40, 50, 60, 80};
const uint8_t rssiBarsHeight[] = {5, 10, 15, 21, 31};

View file

@ -128,7 +128,7 @@ bool menuAboutView(event_t event)
break;
case ABOUT_HARDWARE:
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, "FrSky", INVERS);
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_HARDWARE_1, INVERS);
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_HARDWARE_2);
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_HARDWARE_3);
break;

View file

@ -25,6 +25,8 @@ void menuGhostModuleConfig(event_t event)
switch (event) {
case EVT_ENTRY:
memclear(&reusableBuffer.ghostMenu, sizeof(reusableBuffer.ghostMenu));
strAppend((char *) &reusableBuffer.ghostMenu.line[1].menuText, STR_WAITING_FOR_MODULE, 0);
reusableBuffer.ghostMenu.line[1].lineFlags = GHST_LINE_FLAGS_VALUE_EDIT;
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_NONE;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_OPEN;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
@ -40,6 +42,7 @@ void menuGhostModuleConfig(event_t event)
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYUP;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
audioKeyPress();
break;
#if defined(ROTARY_ENCODER_NAVIGATION)
@ -52,6 +55,7 @@ void menuGhostModuleConfig(event_t event)
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYDOWN;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
audioKeyPress();
break;
@ -59,12 +63,14 @@ void menuGhostModuleConfig(event_t event)
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYPRESS;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
audioKeyPress();
break;
case EVT_KEY_BREAK(KEY_EXIT):
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYLEFT;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
audioKeyPress();
break;
case EVT_KEY_LONG(KEY_EXIT):
@ -78,7 +84,12 @@ void menuGhostModuleConfig(event_t event)
break;
}
if (reusableBuffer.ghostMenu.menuAction == GHST_MENU_CTRL_CLOSE) {
if (reusableBuffer.ghostMenu.menuStatus == GHST_MENU_STATUS_UNOPENED) { // Handles situation where module is plugged after tools start
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_NONE;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_OPEN;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
}
else if (reusableBuffer.ghostMenu.menuStatus == GHST_MENU_STATUS_CLOSING) {
popMenu();
}
@ -104,6 +115,8 @@ void menuGhostModuleConfig(event_t event)
else {
if (reusableBuffer.ghostMenu.line[line].lineFlags & GHST_LINE_FLAGS_LABEL_SELECT)
flags = INVERS;
if (reusableBuffer.ghostMenu.line[line].lineFlags & GHST_LINE_FLAGS_VALUE_EDIT)
flags |= BLINK;
lcdDrawText(xOffset, yOffset + line * FH, reusableBuffer.ghostMenu.line[line].menuText, flags);
}
}

View file

@ -227,14 +227,19 @@ void onSdManagerMenu(const char * result)
#if defined(INTERNAL_MODULE_MULTI)
else if (result == STR_FLASH_INTERNAL_MULTI) {
getSelectionFullPath(lfn);
MultiDeviceFirmwareUpdate device(INTERNAL_MODULE);
MultiDeviceFirmwareUpdate device(INTERNAL_MODULE, MULTI_TYPE_MULTIMODULE);
device.flashFirmware(lfn, drawProgressScreen);
}
#endif
else if (result == STR_FLASH_EXTERNAL_MULTI) {
getSelectionFullPath(lfn);
MultiDeviceFirmwareUpdate device(EXTERNAL_MODULE);
device.flashFirmware(lfn, drawProgressScreen);
device.flashFirmware(lfn, MULTI_TYPE_MULTIMODULE, drawProgressScreen);
}
else if (result == STR_FLASH_EXTERNAL_ELRS) {
getSelectionFullPath(lfn);
MultiDeviceFirmwareUpdate device(EXTERNAL_MODULE);
device.flashFirmware(lfn, MULTI_TYPE_ELRS, drawProgressScreen);
}
#endif
#if defined(BLUETOOTH)
@ -404,6 +409,12 @@ void menuRadioSdManager(event_t _event)
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MULTI);
}
}
if (!READ_ONLY() && !strcasecmp(ext, ELRS_FIRMWARE_EXT)) {
TCHAR lfn[FF_MAX_LFN + 1];
getSelectionFullPath(lfn);
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_ELRS);
}
#endif
#if defined(PCBTARANIS)
if (!READ_ONLY() && !strcasecmp(ext, FIRMWARE_EXT)) {

View file

@ -133,6 +133,7 @@ void menuRadioTools(event_t event)
if (isModuleGhost(EXTERNAL_MODULE))
addRadioModuleTool(index++, "Ghost Menu", menuGhostModuleConfig, EXTERNAL_MODULE);
#endif
if (index == 0) {
lcdDrawCenteredText(LCD_H/2, STR_NO_TOOLS);
}

View file

@ -555,7 +555,7 @@ bool isPxx2IsrmChannelsCountAllowed(int channels)
bool isTrainerUsingModuleBay()
{
#if defined(PCBTARANIS)
if (TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE <= g_model.trainerData.mode && g_model.trainerData.mode <= TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
if (TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE <= g_model.trainerData.mode && g_model.trainerData.mode <= TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
return true;
#endif
return false;
@ -951,8 +951,9 @@ const char STR_SUBTYPE_ESky[] = "\003""Std""ET4";
const char STR_SUBTYPE_MT99[] = "\006""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805";
const char STR_SUBTYPE_MJXQ[] = "\007""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
const char STR_SUBTYPE_FY326[] = "\005""Std\0 ""FY319";
const char STR_SUBTYPE_FUTABA[] = "\005""SFHSS";
const char STR_SUBTYPE_HONTAI[] = "\007""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
const char STR_SUBTYPE_AFHDS2A[] = "\010""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS";
const char STR_SUBTYPE_AFHDS2A[] = "\010""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16";
const char STR_SUBTYPE_Q2X2[] = "\004""Q222""Q242""Q282";
const char STR_SUBTYPE_WK2x01[] = "\006""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
const char STR_SUBTYPE_Q303[] = "\006""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
@ -961,7 +962,7 @@ const char STR_SUBTYPE_ESKY150[] = "\003""4ch""7ch";
const char STR_SUBTYPE_H83D[] = "\007""Std\0 ""H20H\0 ""H20Mini""H30Mini";
const char STR_SUBTYPE_CORONA[] = "\005""V1\0 ""V2\0 ""FD V3";
const char STR_SUBTYPE_HITEC[] = "\007""Optima\0""Opt Hub""Minima\0";
const char STR_SUBTYPE_WFLY[] = "\006""WFR0xS";
const char STR_SUBTYPE_WFLY[] = "\005""WFR0x";
const char STR_SUBTYPE_BUGS_MINI[] = "\006""Std\0 ""Bugs3H";
const char STR_SUBTYPE_TRAXXAS[] = "\004""6519";
const char STR_SUBTYPE_E01X[] = "\005""E012\0""E015\0""E016H";
@ -971,18 +972,24 @@ const char STR_SUBTYPE_V761[] = "\003""3ch""4ch";
const char STR_SUBTYPE_REDPINE[] = "\004""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\003""A20";
const char STR_SUBTYPE_ZSX[] = "\007""280JJRC";
const char STR_SUBTYPE_FLYZONE[] = "\005""FZ410";
const char STR_SUBTYPE_HEIGHT[] = "\003""5ch""8ch";
const char STR_SUBTYPE_FRSKYX_RX[] = "\007""RX\0 ""CloneTX";
const char STR_SUBTYPE_HOTT[] = "\007""Sync\0 ""No_Sync";
const char STR_SUBTYPE_FX816[] = "\003""P38";
const char STR_SUBTYPE_PELIKAN[] = "\004""Pro\0""Lite";
const char STR_SUBTYPE_XK[] = "\004""X450""X420";
const char STR_SUBTYPE_XN297DUMP[] = "\004""250K""1M\0 ""2M\0 ""AUTO""NRF\0";
const char STR_SUBTYPE_FRSKYX2[] = "\011""D16\0 ""D16 8ch\0 ""LBT(EU)\0 ""LBT 8ch\0 ""D16Cloned";
const char STR_SUBTYPE_FRSKYR9[] = "\007""915MHz\0""868MHz\0""915 8ch""868 8ch";
const char STR_SUBTYPE_FRSKYX2[] = "\010""D16\0 ""D16 8ch\0""LBT(EU)\0""LBT 8ch\0""Cloned\0 ""Clone8ch";
const char STR_SUBTYPE_FRSKYR9[] = "\007""915MHz\0""868MHz\0""915 8ch""868 8ch""FCC\0 ""---\0 ""FCC 8ch";
const char STR_SUBTYPE_PROPEL[] = "\004""74-Z";
const char STR_SUBTYPE_FRSKYL[] = "\010""LR12\0 ""LR12 6ch";
const char STR_SUBTYPE_ESKY150V2[] = "\006""150 V2";
const char STR_SUBTYPE_JJRC345[] = "\007""Std\0 ""SkyTmbr";
const char STR_SUBTYPE_KYOSHO[] = "\004""FHSS""Hype";
const char STR_SUBTYPE_RLINK[] = "\007""Surface""Air\0 ""DumboRC";
const char STR_SUBTYPE_ELRS[] = "\007""N/A WIP";
const char STR_SUBTYPE_REALACC[] = "\003""R11";
const char STR_SUBTYPE_WFLY2[] = "\005""RF20x";
const char* mm_options_strings::options[] = {
nullptr,
@ -1017,11 +1024,11 @@ const mm_protocol_definition multi_protocols[] = {
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, false, STR_SUBTYPE_MT99, nullptr},
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FY326, 1, false, false, STR_SUBTYPE_FY326, nullptr},
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FUTABA, 0, true, true, STR_SUBTYPE_FUTABA, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_J6PRO, 0, false, true, NO_SUBTYPE, nullptr},
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, false, STR_SUBTYPE_HONTAI, nullptr},
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, false, NO_SUBTYPE, STR_RF_POWER},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 5, true, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MODULE_SUBTYPE_MULTI_Q2X2, 2, false, false, STR_SUBTYPE_Q2X2, nullptr},
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, true, STR_SUBTYPE_WK2x01, nullptr},
{MODULE_SUBTYPE_MULTI_Q303, 3, false, false, STR_SUBTYPE_Q303, nullptr},
@ -1041,20 +1048,28 @@ const mm_protocol_definition multi_protocols[] = {
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, false, STR_SUBTYPE_POTENSIC, nullptr},
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, false, STR_SUBTYPE_ZSX, nullptr},
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, false, STR_SUBTYPE_FLYZONE, nullptr},
{MODULE_SUBTYPE_MULTI_HEIGHT, 1, false, false, STR_SUBTYPE_HEIGHT, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HOTT, 1, true, false, STR_SUBTYPE_HOTT, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FX816, 0, false, false, STR_SUBTYPE_FX816, nullptr},
{MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, false, STR_SUBTYPE_PELIKAN, nullptr},
{MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, true, STR_SUBTYPE_PELIKAN, nullptr},
{MODULE_SUBTYPE_MULTI_XK, 1, false, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, false, STR_SUBTYPE_XN297DUMP, STR_MULTI_RFCHAN},
{MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, false, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, false, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX2, 5, true, false, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 6, true, false, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_PROPEL, 0, false, false, STR_SUBTYPE_PROPEL, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYL, 1, false, false, STR_SUBTYPE_FRSKYL, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_SKYARTEC, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_ESKY150V2, 0, false, true, STR_SUBTYPE_ESKY150V2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_JJRC345, 1, false, false, STR_SUBTYPE_JJRC345, nullptr},
{MODULE_SUBTYPE_MULTI_Q90C, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_KYOSHO, 1, false, true, STR_SUBTYPE_KYOSHO, nullptr},
{MODULE_SUBTYPE_MULTI_RLINK, 2, false, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_ELRS, 0, false, false, STR_SUBTYPE_ELRS, nullptr},
{MODULE_SUBTYPE_MULTI_REALACC, 0, false, false, STR_SUBTYPE_REALACC, nullptr},
{MODULE_SUBTYPE_MULTI_OMP, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_WFLY2, 0, false, false, STR_SUBTYPE_WFLY2, STR_MULTI_OPTION},
{MODULE_SUBTYPE_MULTI_E016HV2, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MM_RF_CUSTOM_SELECTED, 7, true, true, NO_SUBTYPE, STR_MULTI_OPTION},
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)

View file

@ -248,10 +248,12 @@ inline bool MULTIMODULE_HAS_SUBTYPE(uint8_t moduleIdx)
}
else
{
if (g_model.moduleData[moduleIdx].getMultiProtocol() > MODULE_SUBTYPE_MULTI_LAST)
if (g_model.moduleData[moduleIdx].getMultiProtocol() > MODULE_SUBTYPE_MULTI_LAST) {
return true;
else
return getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol())->maxSubtype > 0;
}
else {
return getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol())->subTypeString != nullptr;
}
}
}
@ -303,9 +305,9 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
#endif
#if defined(AFHDS3)
#define AFHDS3_PROTOCOL_ROW(moduleIdx) isModuleAFHDS3(moduleIdx) ? 0 : HIDDEN_ROW,
#define AFHDS3_PROTOCOL_ROW(moduleIdx) isModuleAFHDS3(moduleIdx) ? uint8_t(0) : HIDDEN_ROW,
#define AFHDS3_MODE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW,
#define AFHDS3_MODULE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? (uint8_t) TITLE_ROW : HIDDEN_ROW,
#define AFHDS3_MODULE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? uint8_t(0) : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW,
#else
#define AFHDS3_PROTOCOL_ROW(moduleIdx)
#define AFHDS3_MODE_ROWS(moduleIdx)

View file

@ -19,6 +19,7 @@
*/
#if !defined(DISABLE_MULTI_UPDATE)
#include "opentx.h"
#include "multi_firmware_update.h"
#include "stk500.h"
@ -51,7 +52,6 @@ class MultiFirmwareUpdateDriver
};
#if defined(INTERNAL_MODULE_MULTI)
class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
{
public:
@ -90,7 +90,6 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
};
static const MultiInternalUpdateDriver multiInternalUpdateDriver;
#endif
class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
@ -150,6 +149,47 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
static const MultiExternalUpdateDriver multiExternalUpdateDriver;
class MultiExtSportUpdateDriver: public MultiFirmwareUpdateDriver
{
public:
MultiExtSportUpdateDriver(): MultiFirmwareUpdateDriver() {}
protected:
void moduleOn() const override
{
EXTERNAL_MODULE_ON();
}
void init(bool inverted) const override
{
telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT);
}
bool getByte(uint8_t & byte) const override
{
return telemetryGetByte(&byte);
}
void sendByte(uint8_t byte) const override
{
sportSendByte(byte);
telemetryPortSetDirectionInput();
}
void clear() const override
{
telemetryClearFifo();
}
void deinit(bool inverted) const override
{
telemetryPortInit(0, 0);
clear();
}
};
static const MultiExtSportUpdateDriver multiExtSportUpdateDriver;
bool MultiFirmwareUpdateDriver::getRxByte(uint8_t & byte) const
{
uint16_t time;
@ -180,6 +220,10 @@ const char * MultiFirmwareUpdateDriver::waitForInitialSync(bool& inverted) const
uint8_t byte;
int retries = 200;
#if defined(DEBUG_EXT_MODULE_FLASH)
TRACE("[Wait for Sync]");
#endif
clear();
do {
@ -204,13 +248,24 @@ const char * MultiFirmwareUpdateDriver::waitForInitialSync(bool& inverted) const
}
if (byte != STK_INSYNC) {
#if defined(DEBUG_EXT_MODULE_FLASH)
TRACE("[byte != STK_INSYNC]");
#endif
return "NoSync";
}
if (!checkRxByte(STK_OK)) {
#if defined(DEBUG_EXT_MODULE_FLASH)
TRACE("[!checkRxByte(STK_OK)]");
#endif
return "NoSync";
}
// avoids sending STK_READ_SIGN with STK_OK
// in case the receiver is too slow changing
// to RX mode (half-duplex).
RTOS_WAIT_TICKS(1);
return nullptr;
}
@ -244,6 +299,10 @@ const char * MultiFirmwareUpdateDriver::loadAddress(uint32_t offset) const
return "NoSync";
}
// avoids sending next page back-to-back with STK_OK
// in case the receiver is to slow changing to RX mode (half-duplex).
RTOS_WAIT_TICKS(1);
return nullptr;
}
@ -261,6 +320,7 @@ const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size)
for (uint16_t i = 0; i < size; i++) {
sendByte(buffer[i]);
}
sendByte(CRC_EOP);
if (!checkRxByte(STK_INSYNC))
@ -486,7 +546,7 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(FIL * file)
return readV1Signature(buffer);
}
bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHandler progressHandler)
bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, MultiModuleType type, ProgressHandler progressHandler)
{
FIL file;
@ -495,6 +555,7 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan
return false;
}
if (type == MULTI_TYPE_MULTIMODULE) {
MultiFirmwareInformation firmwareFile;
if (firmwareFile.readMultiFirmwareInformation(&file)) {
f_close(&file);
@ -517,12 +578,15 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan
return false;
}
}
}
const MultiFirmwareUpdateDriver * driver = &multiExternalUpdateDriver;
#if defined(INTERNAL_MODULE_MULTI)
if (module == INTERNAL_MODULE)
driver = &multiInternalUpdateDriver;
#endif
if (type == MULTI_TYPE_ELRS)
driver = &multiExtSportUpdateDriver;
pausePulses();

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef OPENTX_MULTI_FIRMWARE_H
#define OPENTX_MULTI_FIRMWARE_H
#pragma once
#include "ff.h"
@ -101,6 +100,11 @@ class MultiFirmwareInformation {
const char * readV2Signature(const char * buffer);
};
enum MultiModuleType {
MULTI_TYPE_MULTIMODULE = 0,
MULTI_TYPE_ELRS,
};
class MultiDeviceFirmwareUpdate {
public:
explicit MultiDeviceFirmwareUpdate(ModuleIndex module):
@ -108,10 +112,8 @@ class MultiDeviceFirmwareUpdate {
{
}
bool flashFirmware(const char * filename, ProgressHandler progressHandler);
bool flashFirmware(const char * filename, MultiModuleType type, ProgressHandler progressHandler);
protected:
ModuleIndex module;
};
#endif //OPENTX_MULTI_FIRMWARE_H

View file

@ -76,9 +76,22 @@ constexpr bool IS_VIRTUAL_KEY_EVENT(event_t event)
// normal order of events is: FIRST, LONG, REPEAT, REPEAT, ..., BREAK
#define EVT_KEY_MASK(e) ((e) & 0x1F)
#define EVT_KEY_FIRST(key) ((key)|_MSK_KEY_FIRST) // fired when key is pressed
#define EVT_KEY_LONG(key) ((key)|_MSK_KEY_LONG) // fired when key is held pressed for a while
#define EVT_KEY_REPT(key) ((key)|_MSK_KEY_REPT) // fired when key is held pressed long enough, fires multiple times with increasing speed
constexpr event_t EVT_KEY_FIRST(uint8_t key)
{
return (key | _MSK_KEY_FIRST); // fired when key is pressed
}
constexpr event_t EVT_KEY_REPT(uint8_t key)
{
return (key | _MSK_KEY_REPT); // fired when key is held pressed long enough, fires multiple times with increasing speed
}
constexpr event_t EVT_KEY_LONG(uint8_t key)
{
return (key | _MSK_KEY_LONG); // fired when key is held pressed for a while
}
constexpr event_t EVT_KEY_BREAK(uint8_t key)
{
return (key | _MSK_KEY_BREAK); // fired when key is released (short or long), but only if the event was not killed
@ -94,10 +107,30 @@ constexpr bool IS_TRIM_EVENT(event_t event)
return (IS_KEY_EVENT(event) && EVT_KEY_MASK(event) >= TRM_BASE);
}
#define IS_KEY_FIRST(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_FIRST)
#define IS_KEY_LONG(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_LONG)
#define IS_KEY_REPT(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_REPT)
#define IS_KEY_BREAK(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_BREAK)
inline bool IS_KEY_FIRST(event_t evt)
{
return (evt & _MSK_KEY_FLAGS) == _MSK_KEY_FIRST;
}
inline bool IS_KEY_REPT(event_t evt)
{
return (evt & _MSK_KEY_FLAGS) == _MSK_KEY_REPT;
}
inline bool IS_KEY_LONG(event_t evt)
{
return (evt & _MSK_KEY_FLAGS) == _MSK_KEY_LONG;
}
inline bool IS_KEY_BREAK(event_t evt)
{
return (evt & _MSK_KEY_FLAGS) == _MSK_KEY_BREAK;
}
inline bool IS_KEY_EVT(event_t evt, uint8_t key)
{
return (evt & _MSK_KEY_FLAGS) && (EVT_KEY_MASK(evt) == key);
}
#if defined(PCBXLITE)
#define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER)

View file

@ -71,7 +71,8 @@ Reset the backlight timeout
*/
static int luaLcdResetBacklightTimeout(lua_State * L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
resetBacklightTimeout();
return 0;
}
@ -95,7 +96,8 @@ bottom line is 63. Drawing on an existing black pixel produces white pixel (TODO
*/
static int luaLcdDrawPoint(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
LcdFlags att = luaL_optunsigned(L, 3, 0);
@ -123,7 +125,8 @@ whole line will not be drawn (starting from OpenTX 2.1.5)
*/
static int luaLcdDrawLine(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
coord_t x1 = luaL_checkunsigned(L, 1);
coord_t y1 = luaL_checkunsigned(L, 2);
coord_t x2 = luaL_checkunsigned(L, 3);
@ -228,7 +231,8 @@ See the [Appendix](../appendix/fonts.md) for available characters in each font s
*/
static int luaLcdDrawText(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
const char * s = luaL_checkstring(L, 3);
@ -259,7 +263,8 @@ Display a value formatted as time at (x,y)
*/
static int luaLcdDrawTimer(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int seconds = luaL_checkinteger(L, 3);
@ -293,7 +298,8 @@ Display a number at (x,y)
*/
static int luaLcdDrawNumber(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int val = luaL_checkinteger(L, 3);
@ -321,7 +327,8 @@ See getValue()
*/
static int luaLcdDrawChannel(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int channel = -1;
@ -358,7 +365,8 @@ displays negated switch
*/
static int luaLcdDrawSwitch(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int s = luaL_checkinteger(L, 3);
@ -382,7 +390,8 @@ Displays the name of the corresponding input as defined by the source at (x,y)
*/
static int luaLcdDrawSource(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int s = luaL_checkinteger(L, 3);
@ -532,7 +541,8 @@ Omitting scale draws image in 1:1 scale and is faster than specifying 100 for sc
*/
static int luaLcdDrawBitmap(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
const BitmapBuffer * b = checkBitmap(L, 1);
if (b) {
@ -564,7 +574,8 @@ Draw a bitmap at (x,y)
*/
static int luaLcdDrawPixmap(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
const char * filename = luaL_checkstring(L, 3);
@ -597,7 +608,8 @@ Draw a rectangle from top left corner (x,y) of specified width and height
*/
static int luaLcdDrawRectangle(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int w = luaL_checkinteger(L, 3);
@ -629,7 +641,8 @@ Draw a solid rectangle from top left corner (x,y) of specified width and height
*/
static int luaLcdDrawFilledRectangle(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int w = luaL_checkinteger(L, 3);
@ -661,7 +674,8 @@ Draw a simple gauge that is filled based upon fill value
*/
static int luaLcdDrawGauge(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int w = luaL_checkinteger(L, 3);
@ -699,7 +713,8 @@ the right side of title bar. (i.e. idx=2, cnt=5, display `2/5`)
*/
static int luaLcdDrawScreenTitle(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
const char * str = luaL_checkstring(L, 1);
int idx = luaL_checkinteger(L, 2);
int cnt = luaL_checkinteger(L, 3);
@ -739,7 +754,8 @@ Draw a combo box
*/
static int luaLcdDrawCombobox(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int w = luaL_checkinteger(L, 3);
@ -818,7 +834,13 @@ Set a color for specific area
* `MENU_BGCOLOR`
* `HEADER_ICON_BGCOLOR`
* `HEADER_CURRENT_BGCOLOR`
* `MAINVIEW_PANES_COLOR`
* `MAINVIEW_GRAPHICS_COLOR`
* `OVERLAY_COLOR`
* `BARGRAPH1_COLOR`
* `BARGRAPH2_COLOR`
* `BARGRAPH_BGCOLOR`
* `CUSTOM_COLOR`
@param color (number) color in 5/6/5 rgb format. The following prefined colors are available
* `WHITE`
@ -831,19 +853,40 @@ Set a color for specific area
* `RED`
* `DARKRED`
@notice Only available on Horus
@notice Only available on Colorlcd radios
@status current Introduced in 2.2.0
*/
static int luaLcdSetColor(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
unsigned int index = luaL_checkunsigned(L, 1) >> 16;
unsigned int color = luaL_checkunsigned(L, 2);
lcdColorTable[index] = color;
return 0;
}
/*luadoc
@function lcd.getColor(area)
Get the color for specific area : see lcd.setColor for area list
@notice Only available on Colorlcd radios
@status current Introduced in 2.3.11
*/
static int luaLcdGetColor(lua_State *L)
{
if (!luaLcdAllowed)
return 0;
unsigned int index = luaL_checkunsigned(L, 1) >> 16;
lua_pushunsigned(L, lcdColorTable[index]);
return 1;
}
/*luadoc
@function lcd.RGB(r, g, b)
@ -857,13 +900,14 @@ Returns a 5/6/5 rgb color code, that can be used with lcd.setColor
@retval number (integer) rgb color expressed in 5/6/5 format
@notice Only available on Horus
@notice Only available on Colorlcd radios
@status current Introduced in 2.2.0
*/
static int luaRGB(lua_State *L)
{
if (!luaLcdAllowed) return 0;
if (!luaLcdAllowed)
return 0;
int r = luaL_checkinteger(L, 1);
int g = luaL_checkinteger(L, 2);
int b = luaL_checkinteger(L, 3);
@ -890,6 +934,7 @@ const luaL_Reg lcdLib[] = {
#if defined(COLORLCD)
{ "drawBitmap", luaLcdDrawBitmap },
{ "setColor", luaLcdSetColor },
{ "getColor", luaLcdGetColor },
{ "RGB", luaRGB },
#else
{ "getLastPos", luaLcdGetLastPos },

View file

@ -1518,16 +1518,16 @@ Get Telemetry Sensor parameters
@param sensor (unsigned number) sensor number (use 0 for sensor 1)
@retval nil requested logical switch does not exist
@retval nil requested sensor does not exist
@retval table logical switch data:
* `func` (number) function index
* `v1` (number) V1 value (index)
* `v2` (number) V2 value (index or value)
* `v3` (number) V3 value (index or value)
* `and` (number) AND switch index
* `delay` (number) delay (time in 1/10 s)
* `duration` (number) duration (time in 1/10 s)
@retval table with sensor data:
* `type` (number) 0 = custom, 1 = calculated
* `name` (string) Name
* `unit` (number) See list of units in the appendix of the OpenTX Lua Reference Guide
* `prec` (number) Number of decimals
* `id` (number) Only custom sensors
* `instance` (number) Only custom sensors
* `formula` (number) Only calculated sensors. 0 = Add etc. see list of formula choices in Companion popup
@status current Introduced in 2.3.0
*/
@ -1564,7 +1564,7 @@ Reset Telemetry Sensor parameters
@retval nil
@status current Introduced in 2.3.0
@status current Introduced in 2.3.11
*/
static int luaModelResetSensor(lua_State *L)
{

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef _OPENTX_H_
#define _OPENTX_H_
#pragma once
#include <stdlib.h>
#include "definitions.h"
@ -1115,6 +1114,7 @@ union ReusableBuffer
#if defined(GHOST)
struct {
GhostMenuData line[GHST_MENU_LINES + 1];
uint8_t menuStatus;
uint8_t menuAction;
uint8_t buttonAction;
} ghostMenu;
@ -1313,4 +1313,3 @@ inline bool isAsteriskDisplayed()
#include "thirdparty/libACCESS/libAccess.h"
#endif
#endif // _OPENTX_H_

View file

@ -22,8 +22,6 @@
uint8_t createGhostMenuControlFrame(uint8_t * frame, int16_t * pulses)
{
moduleState[EXTERNAL_MODULE].counter = GHST_FRAME_CHANNEL;
uint8_t * buf = frame;
#if SPORT_MAX_BAUDRATE < 400000
*buf++ = g_eeGeneral.telemetryBaudrate == GHST_TELEMETRY_RATE_400K ? GHST_ADDR_MODULE_SYM : GHST_ADDR_MODULE_ASYM;
@ -118,5 +116,7 @@ void setupPulsesGhost()
extmodulePulsesData.ghost.length = createGhostMenuControlFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]);
else
extmodulePulsesData.ghost.length = createGhostChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]);
moduleState[EXTERNAL_MODULE].counter = GHST_FRAME_CHANNEL;
}
}

View file

@ -121,7 +121,7 @@ enum ModuleSubtypeMulti {
MODULE_SUBTYPE_MULTI_MJXQ,
MODULE_SUBTYPE_MULTI_SHENQI,
MODULE_SUBTYPE_MULTI_FY326,
MODULE_SUBTYPE_MULTI_SFHSS,
MODULE_SUBTYPE_MULTI_FUTABA,
MODULE_SUBTYPE_MULTI_J6PRO, //20
MODULE_SUBTYPE_MULTI_FQ777,
MODULE_SUBTYPE_MULTI_ASSAN,
@ -152,7 +152,7 @@ enum ModuleSubtypeMulti {
MODULE_SUBTYPE_MULTI_REDPINE,
MODULE_SUBTYPE_MULTI_POTENSIC,
MODULE_SUBTYPE_MULTI_ZSX,
MODULE_SUBTYPE_MULTI_FLYZONE, //50
MODULE_SUBTYPE_MULTI_HEIGHT, //50
MODULE_SUBTYPE_MULTI_SCANNER,
MODULE_SUBTYPE_MULTI_FRSKYX_RX,
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
@ -172,7 +172,15 @@ enum ModuleSubtypeMulti {
MODULE_SUBTYPE_MULTI_DSM_RX,
MODULE_SUBTYPE_MULTI_JJRC345,
MODULE_SUBTYPE_MULTI_Q90C,
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_Q90C
MODULE_SUBTYPE_MULTI_KYOSHO, //70
MODULE_SUBTYPE_MULTI_RLINK,
MODULE_SUBTYPE_MULTI_ELRS,
MODULE_SUBTYPE_MULTI_REALACC,
MODULE_SUBTYPE_MULTI_OMP,
MODULE_SUBTYPE_MULTI_MLINK, //75
MODULE_SUBTYPE_MULTI_WFLY2,
MODULE_SUBTYPE_MULTI_E016HV2,
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_E016HV2
};
#define MODULE_SUBTYPE_MULTI_XN297DP 63-3

View file

@ -284,9 +284,14 @@ inline bool isModulePXX1(uint8_t idx)
return isModuleTypePXX1(g_model.moduleData[idx].type);
}
inline bool isModuleXJTLite(uint8_t idx)
{
return g_model.moduleData[idx].type == MODULE_TYPE_XJT_LITE_PXX2;
}
inline bool isModulePXX2(uint8_t idx)
{
return isModuleISRM(idx) || isModuleR9MAccess(idx);
return isModuleISRM(idx) || isModuleR9MAccess(idx) || isModuleXJTLite(idx);
}
inline bool isModuleRFAccess(uint8_t idx)

View file

@ -76,6 +76,7 @@ const char RADIO_SETTINGS_YAML_PATH[] = RADIO_PATH "/radio.yml";
#define SPORT_FIRMWARE_EXT ".frk"
#define FRSKY_FIRMWARE_EXT ".frsk"
#define MULTI_FIRMWARE_EXT ".bin"
#define ELRS_FIRMWARE_EXT ".elrs"
#define YAML_EXT ".yml"
#if defined(COLORLCD)

View file

@ -236,10 +236,6 @@ set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
keys_driver.cpp
diskio.cpp
)
set(TARGET_SRC
${TARGET_SRC}
telemetry_driver.cpp
)

View file

@ -150,7 +150,7 @@ void auxSerialInit(unsigned int mode, unsigned int protocol)
break;
case UART_MODE_SBUS_TRAINER:
auxSerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
auxSerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
AUX_SERIAL_POWER_ON();
break;
@ -238,10 +238,6 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void)
#if defined(LUA) & !defined(CLI)
if (luaRxFifo && auxSerialMode == UART_MODE_LUA)
luaRxFifo->push(data);
#endif
#if !defined(BOOT)
if (auxSerialMode == UART_MODE_SBUS_TRAINER)
trainerSbusFifo.push(data);
#endif
}
status = AUX_SERIAL_USART->SR;
@ -352,7 +348,7 @@ void aux2SerialInit(unsigned int mode, unsigned int protocol)
break;
case UART_MODE_SBUS_TRAINER:
aux2SerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
aux2SerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
AUX2_SERIAL_POWER_ON();
break;
@ -438,11 +434,6 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void)
if (luaRxFifo && aux2SerialMode == UART_MODE_LUA) {
luaRxFifo->push(data);
}
#endif
#if !defined(BOOT)
if (aux2SerialMode == UART_MODE_SBUS_TRAINER) {
trainerSbusFifo.push(data);
}
#endif
}
status = AUX2_SERIAL_USART->SR;

View file

@ -54,27 +54,31 @@
* @{
*/
#define USBD_VID 0x0483
#define USBD_VID_STM 0x0483 // STM Vendor ID
#define USBD_VID_PID_CODES 0x1209 // https://pid.codes
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "OpenTX"
#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
#if defined(BOOT)
#define USBD_MSC_PRODUCT_FS_STRING USB_NAME " Bootloader"
#else
#define USBD_MSC_PRODUCT_FS_STRING USB_NAME " Mass Storage"
#endif
#define USBD_MSC_VID USBD_VID_STM
#define USBD_MSC_PID 0x5720
#define USBD_MSC_CONFIGURATION_FS_STRING "MSC Config"
#define USBD_MSC_INTERFACE_FS_STRING "MSC Interface"
#define USBD_HID_PID 0x5710
#define USBD_HID_VID USBD_VID_PID_CODES
#define USBD_HID_PID 0x4F54 // OpenTX assigned PID
#define USBD_HID_PRODUCT_FS_STRING USB_NAME " Joystick"
#define USBD_HID_CONFIGURATION_FS_STRING "HID Config"
#define USBD_HID_INTERFACE_FS_STRING "HID Interface"
#define USBD_CDC_VID USBD_VID_STM
#define USBD_CDC_PID 0x5740 // do not change, this ID is used by the ST USB driver for Windows
#define USBD_CDC_PRODUCT_FS_STRING USB_NAME " Serial Port"
#define USBD_CDC_CONFIGURATION_FS_STRING "VSP Config"
@ -127,18 +131,27 @@ __ALIGN_BEGIN uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ] __ALIGN_END ; // modifi
*/
uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length)
{
int pid=0;
int vid, pid;
switch (getSelectedUsbMode()) {
case USB_JOYSTICK_MODE:
vid = USBD_HID_VID;
pid = USBD_HID_PID;
break;
case USB_SERIAL_MODE:
vid = USBD_CDC_VID;
pid = USBD_CDC_PID;
break;
case USB_MASS_STORAGE_MODE:
vid = USBD_MSC_VID;
pid = USBD_MSC_PID;
break;
default:
vid = 0;
pid = 0;
}
/* USB Standard Device Descriptor */
@ -152,8 +165,8 @@ uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length)
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
USB_OTG_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(vid), /*idVendor*/
HIBYTE(vid), /*idVendor*/
LOBYTE(pid), /*idVendor*/
HIBYTE(pid), /*idVendor*/
0x00, /*bcdDevice rel. 2.00*/

View file

@ -637,7 +637,11 @@ void sportUpdatePowerInit();
#endif
// Aux serial port driver
#if defined(RADIO_TX16S)
#define DEBUG_BAUDRATE 400000
#else
#define DEBUG_BAUDRATE 115200
#endif
#if defined(AUX_SERIAL_GPIO)
extern uint8_t auxSerialMode;
void auxSerialInit(unsigned int mode, unsigned int protocol);
@ -711,6 +715,7 @@ void bluetoothDisable();
extern DMAFifo<512> telemetryFifo;
typedef DMAFifo<32> AuxSerialRxFifo;
extern AuxSerialRxFifo auxSerialRxFifo;
extern AuxSerialRxFifo aux2SerialRxFifo;
extern volatile uint32_t externalModulePort;
#endif

View file

@ -160,9 +160,16 @@ extern "C" void TRAINER_TIMER_IRQHandler()
int sbusGetByte(uint8_t * byte)
{
switch (currentTrainerMode) {
#if defined(AUX_SERIAL)
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT:
return trainerSbusFifo.pop(*byte);
#if defined(AUX_SERIAL)
if (auxSerialMode == UART_MODE_SBUS_TRAINER)
return auxSerialRxFifo.pop(*byte);
#endif
#if defined(AUX2_SERIAL)
if (aux2SerialMode == UART_MODE_SBUS_TRAINER)
return aux2SerialRxFifo.pop(*byte);
#endif
#endif
default:
return false;

View file

@ -42,6 +42,8 @@ char * main_thread_error = nullptr;
bool simu_shutdown = false;
bool simu_running = false;
uint32_t telemetryErrors = 0;
#if defined(STM32)
GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpioi, gpioj;
TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10;
@ -470,6 +472,47 @@ void sportUpdatePowerInit()
{
}
void telemetryPortSetDirectionInput()
{
}
void telemetryPortSetDirectionOutput()
{
}
void rxPdcUsart( void (*pChProcess)(uint8_t x) )
{
}
void telemetryPortInit(uint32_t baudrate, uint8_t mode)
{
}
bool telemetryGetByte(uint8_t * byte)
{
return false;
}
void telemetryClearFifo()
{
}
void telemetryPortInvertedInit(uint32_t baudrate)
{
}
void sportSendByte(uint8_t byte)
{
}
void sportSendBuffer(const uint8_t * buffer, uint32_t count)
{
}
void check_telemetry_exti()
{
}
void boardInit()
{
}

View file

@ -125,9 +125,13 @@ set(FIRMWARE_TARGET_SRC
MEDSdcard.c
)
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
telemetry_driver.cpp
)
set(TARGET_SRC
${TARGET_SRC}
telemetry_driver.cpp
adc_driver.cpp
pulses_driver.cpp
audio_driver.cpp

View file

@ -399,10 +399,8 @@ void debugPutc(const char c);
// Telemetry driver
void telemetryPortInit(uint32_t baudrate, uint8_t mode);
inline void telemetryPortSetDirectionOutput()
{
}
uint32_t telemetryTransmitPending();
void telemetryPortSetDirectionOutput();
void telemetryPortSetDirectionInput();
void telemetryTransmitBuffer(const uint8_t * buffer, uint32_t size);
void rxPdcUsart( void (*pChProcess)(uint8_t x) );
void sportSendBuffer(const uint8_t * buffer, uint32_t size);

View file

@ -93,10 +93,8 @@ void startPdcUsartReceive()
{
Usart *pUsart = SECOND_USART;
TelemetryInBuffer.outPtr = TelemetryInBuffer.fifo ;
#ifndef SIMU
pUsart->US_RPR = (uint32_t)TelemetryInBuffer.fifo ;
pUsart->US_RNPR = (uint32_t)TelemetryInBuffer.fifo ;
#endif
pUsart->US_RCR = RX_UART_BUFFER_SIZE ;
pUsart->US_RNCR = RX_UART_BUFFER_SIZE ;
pUsart->US_PTCR = US_PTCR_RXTEN ;
@ -104,7 +102,6 @@ void startPdcUsartReceive()
void rxPdcUsart( void (*pChProcess)(uint8_t x) )
{
#if !defined(SIMU)
Usart *pUsart = SECOND_USART;
uint8_t *ptr ;
uint8_t *endPtr ;
@ -132,7 +129,6 @@ void rxPdcUsart( void (*pChProcess)(uint8_t x) )
pUsart->US_RNPR = (uint32_t)TelemetryInBuffer.fifo ;
pUsart->US_RNCR = RX_UART_BUFFER_SIZE ;
}
#endif
}
uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size)
@ -140,9 +136,7 @@ uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size)
Usart * pUsart = SECOND_USART;
if (pUsart->US_TNCR == 0) {
#ifndef SIMU
pUsart->US_TNPR = (uint32_t)buffer ;
#endif
pUsart->US_TNCR = size ;
pUsart->US_PTCR = US_PTCR_TXTEN ;
return 1 ;
@ -150,6 +144,7 @@ uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size)
return 0 ;
}
/*
uint32_t telemetryTransmitPending()
{
Usart *pUsart = SECOND_USART;
@ -164,13 +159,20 @@ uint32_t telemetryTransmitPending()
return x ;
}
*/
void telemetryPortSetDirectionOutput()
{
}
void telemetryPortSetDirectionInput()
{
}
void telemetryPortInit(uint32_t baudrate, uint8_t mode)
{
#if !defined(SIMU)
UART2_Configure(baudrate, Master_frequency, mode);
startPdcUsartReceive();
#endif
}
void sportSendBuffer(const uint8_t * buffer, uint32_t size)

View file

@ -135,7 +135,6 @@ elseif(PCB STREQUAL X7)
set(LUA_EXPORT lua_export_t12)
add_definitions(-DRADIO_T12)
add_definitions(-DEEPROM_VARIANT=0x4001)
add_definitions(-DMANUFACTURER_JUMPER)
elseif(PCBREV STREQUAL TX12)
option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" ON)
set(FLAVOUR tx12)
@ -146,6 +145,7 @@ elseif(PCB STREQUAL X7)
set(ROTARY_ENCODER YES)
set(LUA_EXPORT lua_export_tx12)
set(BLUETOOTH NO)
set(USB_CHARGER YES)
add_definitions(-DRADIO_TX12)
add_definitions(-DEEPROM_VARIANT=0x4002)
add_definitions(-DMANUFACTURER_RADIOMASTER)
@ -347,6 +347,11 @@ if(ROTARY_ENCODER)
)
endif()
if(USB_CHARGER)
set(TARGET_SRC ${TARGET_SRC} usb_charger_driver.cpp)
add_definitions(-DUSB_CHARGER)
endif()
if(BLUETOOTH)
add_definitions(-DBLUETOOTH)
set(TARGET_SRC

View file

@ -92,7 +92,8 @@ void boardInit()
TRAINER_RCC_AHB1Periph |
TRAINER_MODULE_RCC_AHB1Periph |
BT_RCC_AHB1Periph |
GYRO_RCC_AHB1Periph,
GYRO_RCC_AHB1Periph |
USB_CHARGER_RCC_AHB1Periph,
ENABLE);
RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph |
@ -193,6 +194,10 @@ void boardInit()
toplcdInit();
#endif
#if defined(USB_CHARGER)
usbChargerInit();
#endif
if (HAS_SPORT_UPDATE_CONNECTOR()) {
sportUpdateInit();
}

View file

@ -863,6 +863,10 @@ void bluetoothDisable();
#define IS_BLUETOOTH_CHIP_PRESENT() (true)
#endif
// USB Charger
void usbChargerInit();
bool usbChargerLed();
// LED driver
void ledInit();
void ledOff();

View file

@ -1431,6 +1431,16 @@
#define PCBREV_RCC_AHB1Periph 0
#endif
// USB Charger
#if defined(USB_CHARGER)
#define USB_CHARGER_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
#define USB_CHARGER_GPIO GPIOB
#define USB_CHARGER_GPIO_PIN GPIO_Pin_5 // PB.05
#else
#define USB_CHARGER_RCC_AHB1Periph 0
#endif
// S.Port update connector
#if defined(PCBXLITE)
#define SPORT_MAX_BAUDRATE 250000 // not tested
@ -1446,7 +1456,7 @@
#define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_3 // PB.03
#define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
#define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
#elif defined(PCBX7)
#elif defined(RADIO_X7)
#define SPORT_MAX_BAUDRATE 250000 // < 400000
#define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
#define SPORT_UPDATE_PWR_GPIO GPIOB

View file

@ -0,0 +1,37 @@
/*
* 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 "opentx.h"
void usbChargerInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = USB_CHARGER_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(USB_CHARGER_GPIO, &GPIO_InitStructure);
}
bool usbChargerLed()
{
return (GPIO_ReadInputDataBit(USB_CHARGER_GPIO, USB_CHARGER_GPIO_PIN) == Bit_RESET && usbPlugged());
}

View file

@ -192,11 +192,10 @@ void processGhostTelemetryFrame()
{
GhostMenuFrame * packet;
GhostMenuData * lineData;
packet = (GhostMenuFrame * ) telemetryRxBuffer;
lineData = (GhostMenuData *) &reusableBuffer.ghostMenu.line[packet->lineIndex];
lineData->splitLine = 0;
reusableBuffer.ghostMenu.menuAction = packet->menuFlags;
reusableBuffer.ghostMenu.menuStatus = packet->menuStatus;
lineData->lineFlags = packet->lineFlags;
for (uint8_t i = 0; i < GHST_MENU_CHARS; i++) {
if (packet->menuText[i] == 0x7C) {
@ -208,8 +207,6 @@ void processGhostTelemetryFrame()
}
}
lineData->menuText[GHST_MENU_CHARS] = '\0';
if (packet->lineIndex == GHST_MENU_LINES - 1)
lineData->menuUpdateNeeded = true;
break;
}

View file

@ -142,6 +142,13 @@ enum GhostMenuControl
GHST_MENU_CTRL_REDRAW = 0X04,
};
enum GhostMenuStatus
{
GHST_MENU_STATUS_UNOPENED = 0x00,
GHST_MENU_STATUS_OPENED = 0x01,
GHST_MENU_STATUS_CLOSING = 0x02,
};
enum GhostFrames
{
GHST_FRAME_CHANNEL,
@ -157,8 +164,8 @@ struct GhostMenuFrame
uint8_t address;
uint8_t length ;
uint8_t packetId;
uint8_t menuFlags; // GHST_MENU_CTRL
uint8_t lineFlags; // Carat states, Inverse, Bold for each of Menu Label, and Value
uint8_t menuStatus; // GhostMenuStatus
uint8_t lineFlags; // GhostLineFlags
uint8_t lineIndex; // 0 = first line
unsigned char menuText[GHST_MENU_CHARS];
uint8_t crc;
@ -166,9 +173,9 @@ struct GhostMenuFrame
struct GhostMenuData
{
uint8_t menuFlags; // Update Line, Clear Menu, etc.
uint8_t menuStatus; // Update Line, Clear Menu, etc.
uint8_t lineFlags; // Carat states, Inverse, Bold for each of Menu Label, and Value
uint8_t splitLine; // Store beginning of Value substring
char menuText[GHST_MENU_CHARS + 1];
uint8_t menuUpdateNeeded;
};

Some files were not shown because too many files have changed in this diff Show more